mirror of
https://github.com/fluencelabs/parity-wasm
synced 2025-04-24 23:02:15 +00:00
Merge 'origin/master' into api-overhaul
Conflicts: src/interpreter/native.rs src/interpreter/runner.rs src/interpreter/tests/wabt.rs src/interpreter/validator.rs
This commit is contained in:
commit
367807663d
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "parity-wasm"
|
||||
version = "0.19.0"
|
||||
version = "0.20.0"
|
||||
authors = ["Nikolay Volf <nikvolf@gmail.com>", "Svyatoslav Nikolsky <svyatonik@yandex.ru>", "Sergey Shulepov <s.pepyakin@gmail.com>"]
|
||||
license = "MIT/Apache-2.0"
|
||||
readme = "README.md"
|
||||
|
@ -13,8 +13,8 @@ along with experimental interpreter
|
||||
|
||||
extern crate parity_wasm;
|
||||
|
||||
let module = parity_wasm::deserialize_file("./res/cases/v1/hello.wasm");
|
||||
assert_eq!(module.code_section().is_some());
|
||||
let module = parity_wasm::deserialize_file("./res/cases/v1/hello.wasm").unwrap();
|
||||
assert!(module.code_section().is_some());
|
||||
|
||||
let code_section = module.code_section().unwrap(); // Part of the module with functions code
|
||||
|
||||
|
@ -2,61 +2,73 @@ use elements;
|
||||
use super::invoke::{Invoke, Identity};
|
||||
use super::misc::{ValueTypeBuilder, ValueTypesBuilder, OptionalValueTypeBuilder};
|
||||
|
||||
/// Signature template description
|
||||
pub enum Signature {
|
||||
TypeReference(u32),
|
||||
Inline(elements::FunctionType),
|
||||
}
|
||||
|
||||
/// Signature builder
|
||||
pub struct SignatureBuilder<F=Identity> {
|
||||
callback: F,
|
||||
signature: elements::FunctionType,
|
||||
}
|
||||
|
||||
impl SignatureBuilder {
|
||||
/// New signature builder
|
||||
pub fn new() -> Self {
|
||||
SignatureBuilder::with_callback(Identity)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> SignatureBuilder<F> where F: Invoke<elements::FunctionType> {
|
||||
/// New builder with callback function specified
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
SignatureBuilder {
|
||||
callback: callback,
|
||||
SignatureBuilder {
|
||||
callback: callback,
|
||||
signature: elements::FunctionType::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Add argument to signature builder
|
||||
pub fn with_param(mut self, value_type: elements::ValueType) -> Self {
|
||||
self.signature.params_mut().push(value_type);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add multiple arguments to signature builder
|
||||
pub fn with_params(mut self, value_types: Vec<elements::ValueType>) -> Self {
|
||||
self.signature.params_mut().extend(value_types);
|
||||
self
|
||||
}
|
||||
|
||||
/// Override signature return type
|
||||
pub fn with_return_type(mut self, return_type: Option<elements::ValueType>) -> Self {
|
||||
*self.signature.return_type_mut() = return_type;
|
||||
self
|
||||
}
|
||||
|
||||
/// Start build new argument
|
||||
pub fn param(self) -> ValueTypeBuilder<Self> {
|
||||
ValueTypeBuilder::with_callback(self)
|
||||
}
|
||||
|
||||
/// Start build multiple arguments
|
||||
pub fn params(self) -> ValueTypesBuilder<Self> {
|
||||
ValueTypesBuilder::with_callback(self)
|
||||
}
|
||||
|
||||
/// Start building return type
|
||||
pub fn return_type(self) -> OptionalValueTypeBuilder<Self> {
|
||||
OptionalValueTypeBuilder::with_callback(self)
|
||||
}
|
||||
|
||||
/// Finish current builder
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(self.signature)
|
||||
}
|
||||
|
||||
/// Finish current builder returning intermediate `Signature` struct
|
||||
pub fn build_sig(self) -> Signature {
|
||||
Signature::Inline(self.signature)
|
||||
}
|
||||
@ -82,8 +94,8 @@ impl<F> Invoke<Option<elements::ValueType>> for SignatureBuilder<F>
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Invoke<elements::ValueType> for SignatureBuilder<F>
|
||||
where F: Invoke<elements::FunctionType>
|
||||
impl<F> Invoke<elements::ValueType> for SignatureBuilder<F>
|
||||
where F: Invoke<elements::FunctionType>
|
||||
{
|
||||
type Result = Self;
|
||||
|
||||
@ -92,27 +104,32 @@ impl<F> Invoke<elements::ValueType> for SignatureBuilder<F>
|
||||
}
|
||||
}
|
||||
|
||||
/// Type (signature) reference builder (for function/import/indirect call)
|
||||
pub struct TypeRefBuilder<F=Identity> {
|
||||
callback: F,
|
||||
type_ref: u32,
|
||||
}
|
||||
|
||||
impl<F> TypeRefBuilder<F> where F: Invoke<u32> {
|
||||
/// New builder chained with specified callback
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
TypeRefBuilder {
|
||||
callback: callback,
|
||||
TypeRefBuilder {
|
||||
callback: callback,
|
||||
type_ref: 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Set/override of type reference
|
||||
pub fn val(mut self, val: u32) -> Self {
|
||||
self.type_ref = val;
|
||||
self
|
||||
}
|
||||
|
||||
/// Finish current builder
|
||||
pub fn build(self) -> F::Result { self.callback.invoke(self.type_ref) }
|
||||
}
|
||||
|
||||
/// Multiple signatures builder
|
||||
pub struct SignaturesBuilder<F=Identity> {
|
||||
callback: F,
|
||||
section: Vec<Signature>,
|
||||
@ -126,6 +143,7 @@ impl SignaturesBuilder {
|
||||
}
|
||||
|
||||
impl<F> SignaturesBuilder<F> {
|
||||
/// New builder chained with specified callback
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
SignaturesBuilder {
|
||||
callback: callback,
|
||||
@ -133,17 +151,20 @@ impl<F> SignaturesBuilder<F> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Push new signature into the builder output
|
||||
pub fn with_signature(mut self, signature: Signature) -> Self {
|
||||
self.section.push(signature);
|
||||
self
|
||||
}
|
||||
|
||||
/// Start building new signature with `TypeRefBuilder`
|
||||
pub fn type_ref(self) -> TypeRefBuilder<Self> {
|
||||
TypeRefBuilder::with_callback(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
|
||||
/// Start building new signature with dedicated builder
|
||||
pub fn signature(self) -> SignatureBuilder<Self> {
|
||||
SignatureBuilder::with_callback(self)
|
||||
}
|
||||
@ -154,7 +175,7 @@ impl<F> Invoke<elements::FunctionType> for SignaturesBuilder<F> {
|
||||
|
||||
fn invoke(self, signature: elements::FunctionType) -> Self {
|
||||
self.with_signature(Signature::Inline(signature))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Invoke<u32> for SignaturesBuilder<F> {
|
||||
@ -162,10 +183,12 @@ impl<F> Invoke<u32> for SignaturesBuilder<F> {
|
||||
|
||||
fn invoke(self, type_ref: u32) -> Self {
|
||||
self.with_signature(Signature::TypeReference(type_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> SignaturesBuilder<F> where F: Invoke<elements::FunctionSection> {
|
||||
|
||||
/// Finalize builder spawning element
|
||||
pub fn build(self) -> F::Result {
|
||||
let mut result = elements::FunctionSection::default();
|
||||
for f in self.section.into_iter() {
|
||||
@ -179,20 +202,24 @@ impl<F> SignaturesBuilder<F> where F: Invoke<elements::FunctionSection> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Signature bindings
|
||||
pub type SignatureBindings = Vec<Signature>;
|
||||
|
||||
impl<F> SignaturesBuilder<F> where F: Invoke<SignatureBindings> {
|
||||
/// Bind signature list
|
||||
pub fn bind(self) -> F::Result {
|
||||
self.callback.invoke(self.section)
|
||||
}
|
||||
}
|
||||
|
||||
/// Function body (code) builder
|
||||
pub struct FuncBodyBuilder<F=Identity> {
|
||||
callback: F,
|
||||
body: elements::FuncBody,
|
||||
}
|
||||
|
||||
impl<F> FuncBodyBuilder<F> {
|
||||
/// New body (code) builder given the chain callback
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
FuncBodyBuilder {
|
||||
callback: callback,
|
||||
@ -202,29 +229,37 @@ impl<F> FuncBodyBuilder<F> {
|
||||
}
|
||||
|
||||
impl<F> FuncBodyBuilder<F> where F: Invoke<elements::FuncBody> {
|
||||
/// Set/override entirely with FuncBody struct
|
||||
pub fn with_func(mut self, func: elements::FuncBody) -> Self {
|
||||
self.body = func;
|
||||
self
|
||||
}
|
||||
|
||||
/// Extend function local list with new entries
|
||||
pub fn with_locals(mut self, locals: Vec<elements::Local>) -> Self {
|
||||
self.body.locals_mut().extend(locals);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set code of the function
|
||||
pub fn with_opcodes(mut self, opcodes: elements::Opcodes) -> Self {
|
||||
*self.body.code_mut() = opcodes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Finish current builder spawning resulting struct
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(self.body)
|
||||
}
|
||||
}
|
||||
|
||||
/// Function definition (extended structure to specify function entirely, incl. signature, mainness and code)
|
||||
pub struct FunctionDefinition {
|
||||
/// Is this function is start function
|
||||
pub is_main: bool,
|
||||
/// Signature description
|
||||
pub signature: Signature,
|
||||
/// Body (code) of the function
|
||||
pub code: elements::FuncBody,
|
||||
}
|
||||
|
||||
@ -238,18 +273,21 @@ impl Default for FunctionDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
/// Function definition builder
|
||||
pub struct FunctionBuilder<F=Identity> {
|
||||
callback: F,
|
||||
func: FunctionDefinition,
|
||||
}
|
||||
|
||||
impl FunctionBuilder {
|
||||
/// New function builder
|
||||
pub fn new() -> Self {
|
||||
FunctionBuilder::with_callback(Identity)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
||||
/// New function builder with chained callback
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
FunctionBuilder {
|
||||
callback: callback,
|
||||
@ -257,29 +295,35 @@ impl<F> FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set that this function is main entry point
|
||||
pub fn main(mut self) -> Self {
|
||||
self.func.is_main = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Start signature builder of the function
|
||||
pub fn signature(self) -> SignatureBuilder<Self> {
|
||||
SignatureBuilder::with_callback(self)
|
||||
}
|
||||
|
||||
/// Override current signature entirely with new one from known struct
|
||||
pub fn with_signature(mut self, signature: Signature) -> Self {
|
||||
self.func.signature = signature;
|
||||
self
|
||||
}
|
||||
|
||||
/// Start code (body) builder
|
||||
pub fn body(self) -> FuncBodyBuilder<Self> {
|
||||
FuncBodyBuilder::with_callback(self)
|
||||
}
|
||||
|
||||
/// Set body (code) for this function
|
||||
pub fn with_body(mut self, body: elements::FuncBody) -> Self {
|
||||
self.func.code = body;
|
||||
self
|
||||
}
|
||||
|
||||
/// Finalize current builder spawning resulting struct in the callback
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(self.func)
|
||||
}
|
||||
@ -290,7 +334,7 @@ impl<F> Invoke<elements::FunctionType> for FunctionBuilder<F> where F: Invoke<Fu
|
||||
|
||||
fn invoke(self, signature: elements::FunctionType) -> Self {
|
||||
self.with_signature(Signature::Inline(signature))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Invoke<u32> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
||||
@ -298,7 +342,7 @@ impl<F> Invoke<u32> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
||||
|
||||
fn invoke(self, type_ref: u32) -> Self {
|
||||
self.with_signature(Signature::TypeReference(type_ref))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Invoke<elements::FuncBody> for FunctionBuilder<F> where F: Invoke<FunctionDefinition> {
|
||||
@ -344,7 +388,7 @@ mod tests {
|
||||
.param().i32()
|
||||
.return_type().i64()
|
||||
.build()
|
||||
.bind();
|
||||
.bind();
|
||||
|
||||
assert_eq!(result.len(), 1);
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::invoke::{Identity, Invoke};
|
||||
use elements;
|
||||
|
||||
/// Data segment builder
|
||||
pub struct DataSegmentBuilder<F=Identity> {
|
||||
callback: F,
|
||||
// todo: add mapper once multiple memory refs possible
|
||||
@ -10,12 +11,14 @@ pub struct DataSegmentBuilder<F=Identity> {
|
||||
}
|
||||
|
||||
impl DataSegmentBuilder {
|
||||
/// New data segment builder
|
||||
pub fn new() -> Self {
|
||||
DataSegmentBuilder::with_callback(Identity)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> DataSegmentBuilder<F> {
|
||||
/// New data segment builder inside the chain context
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
DataSegmentBuilder {
|
||||
callback: callback,
|
||||
@ -25,11 +28,13 @@ impl<F> DataSegmentBuilder<F> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set offset initialization opcode. `End` opcode will be added automatically.
|
||||
pub fn offset(mut self, opcode: elements::Opcode) -> Self {
|
||||
self.offset = elements::InitExpr::new(vec![opcode, elements::Opcode::End]);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the bytes value of the segment
|
||||
pub fn value(mut self, value: Vec<u8>) -> Self {
|
||||
self.value = value;
|
||||
self
|
||||
@ -37,6 +42,7 @@ impl<F> DataSegmentBuilder<F> {
|
||||
}
|
||||
|
||||
impl<F> DataSegmentBuilder<F> where F: Invoke<elements::DataSegment> {
|
||||
/// Finish current builder, spawning resulting struct
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(
|
||||
elements::DataSegment::new(
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::invoke::{Invoke, Identity};
|
||||
use elements;
|
||||
|
||||
/// Export entry builder
|
||||
pub struct ExportBuilder<F=Identity> {
|
||||
callback: F,
|
||||
field: String,
|
||||
@ -8,6 +9,7 @@ pub struct ExportBuilder<F=Identity> {
|
||||
}
|
||||
|
||||
impl ExportBuilder {
|
||||
/// New export builder
|
||||
pub fn new() -> Self {
|
||||
ExportBuilder::with_callback(Identity)
|
||||
}
|
||||
@ -15,6 +17,7 @@ impl ExportBuilder {
|
||||
|
||||
impl<F> ExportBuilder<F> {
|
||||
|
||||
/// New export entry builder in the specified chained context
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
ExportBuilder {
|
||||
callback: callback,
|
||||
@ -23,22 +26,26 @@ impl<F> ExportBuilder<F> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the field name of the export entry
|
||||
pub fn field(mut self, field: &str) -> Self {
|
||||
self.field = field.to_owned();
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify the internal module mapping for this entry
|
||||
pub fn with_internal(mut self, external: elements::Internal) -> Self {
|
||||
self.binding = external;
|
||||
self
|
||||
}
|
||||
|
||||
/// Start the internal builder for this export entry
|
||||
pub fn internal(self) -> ExportInternalBuilder<Self> {
|
||||
ExportInternalBuilder::with_callback(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> ExportBuilder<F> where F: Invoke<elements::ExportEntry> {
|
||||
/// Finalize export entry builder spawning the resulting struct
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(elements::ExportEntry::new(self.field, self.binding))
|
||||
}
|
||||
@ -51,12 +58,14 @@ impl<F> Invoke<elements::Internal> for ExportBuilder<F> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Internal mapping builder for export entry
|
||||
pub struct ExportInternalBuilder<F=Identity> {
|
||||
callback: F,
|
||||
binding: elements::Internal,
|
||||
}
|
||||
|
||||
impl<F> ExportInternalBuilder<F> where F: Invoke<elements::Internal> {
|
||||
/// New export entry internal mapping for the chained context
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
ExportInternalBuilder{
|
||||
callback: callback,
|
||||
@ -64,21 +73,25 @@ impl<F> ExportInternalBuilder<F> where F: Invoke<elements::Internal> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Map to function by index
|
||||
pub fn func(mut self, index: u32) -> F::Result {
|
||||
self.binding = elements::Internal::Function(index);
|
||||
self.callback.invoke(self.binding)
|
||||
}
|
||||
|
||||
/// Map to memory
|
||||
pub fn memory(mut self, index: u32) -> F::Result {
|
||||
self.binding = elements::Internal::Memory(index);
|
||||
self.callback.invoke(self.binding)
|
||||
}
|
||||
|
||||
/// Map to table
|
||||
pub fn table(mut self, index: u32) -> F::Result {
|
||||
self.binding = elements::Internal::Table(index);
|
||||
self.callback.invoke(self.binding)
|
||||
}
|
||||
|
||||
/// Map to global
|
||||
pub fn global(mut self, index: u32) -> F::Result {
|
||||
self.binding = elements::Internal::Global(index);
|
||||
self.callback.invoke(self.binding)
|
||||
|
@ -2,6 +2,7 @@ use super::invoke::{Invoke, Identity};
|
||||
use super::misc::ValueTypeBuilder;
|
||||
use elements;
|
||||
|
||||
/// Global builder
|
||||
pub struct GlobalBuilder<F=Identity> {
|
||||
callback: F,
|
||||
value_type: elements::ValueType,
|
||||
@ -10,12 +11,14 @@ pub struct GlobalBuilder<F=Identity> {
|
||||
}
|
||||
|
||||
impl GlobalBuilder {
|
||||
/// New global builder
|
||||
pub fn new() -> Self {
|
||||
GlobalBuilder::with_callback(Identity)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> GlobalBuilder<F> {
|
||||
/// New global builder with callback (in chained context)
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
GlobalBuilder {
|
||||
callback: callback,
|
||||
@ -25,31 +28,36 @@ impl<F> GlobalBuilder<F> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set/override resulting global type
|
||||
pub fn with_type(mut self, value_type: elements::ValueType) -> Self {
|
||||
self.value_type = value_type;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set mutabilty to true
|
||||
pub fn mutable(mut self) -> Self {
|
||||
self.is_mutable = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set initialization expression opcode for this global (`end` opcode will be added automatically)
|
||||
pub fn init_expr(mut self, opcode: elements::Opcode) -> Self {
|
||||
self.init_expr = elements::InitExpr::new(vec![opcode, elements::Opcode::End]);
|
||||
self
|
||||
}
|
||||
|
||||
/// Start value type builder
|
||||
pub fn value_type(self) -> ValueTypeBuilder<Self> {
|
||||
ValueTypeBuilder::with_callback(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> GlobalBuilder<F> where F: Invoke<elements::GlobalEntry> {
|
||||
/// Finalize current builder spawning resulting struct
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(
|
||||
elements::GlobalEntry::new(
|
||||
elements::GlobalType::new(self.value_type, self.is_mutable),
|
||||
elements::GlobalType::new(self.value_type, self.is_mutable),
|
||||
self.init_expr,
|
||||
)
|
||||
)
|
||||
|
@ -1,6 +1,7 @@
|
||||
use super::invoke::{Invoke, Identity};
|
||||
use elements;
|
||||
|
||||
/// Import builder
|
||||
pub struct ImportBuilder<F=Identity> {
|
||||
callback: F,
|
||||
module: String,
|
||||
@ -9,13 +10,14 @@ pub struct ImportBuilder<F=Identity> {
|
||||
}
|
||||
|
||||
impl ImportBuilder {
|
||||
/// New import builder
|
||||
pub fn new() -> Self {
|
||||
ImportBuilder::with_callback(Identity)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> ImportBuilder<F> {
|
||||
|
||||
/// New import builder with callback (in chained context)
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
ImportBuilder {
|
||||
callback: callback,
|
||||
@ -25,31 +27,37 @@ impl<F> ImportBuilder<F> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set/override module name
|
||||
pub fn module(mut self, name: &str) -> Self {
|
||||
self.module = name.to_owned();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set/override field name
|
||||
pub fn field(mut self, name: &str) -> Self {
|
||||
self.field = name.to_owned();
|
||||
self
|
||||
}
|
||||
|
||||
/// Set/override both module name and field name
|
||||
pub fn path(self, module: &str, field: &str) -> Self {
|
||||
self.module(module).field(field)
|
||||
}
|
||||
|
||||
/// Set/override external mapping for this import
|
||||
pub fn with_external(mut self, external: elements::External) -> Self {
|
||||
self.binding = external;
|
||||
self
|
||||
}
|
||||
|
||||
/// Start new external mapping builder
|
||||
pub fn external(self) -> ImportExternalBuilder<Self> {
|
||||
ImportExternalBuilder::with_callback(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> ImportBuilder<F> where F: Invoke<elements::ImportEntry> {
|
||||
/// Finalize current builder spawning the resulting struct
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(elements::ImportEntry::new(self.module, self.field, self.binding))
|
||||
}
|
||||
@ -62,12 +70,14 @@ impl<F> Invoke<elements::External> for ImportBuilder<F> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Import to external mapping builder
|
||||
pub struct ImportExternalBuilder<F=Identity> {
|
||||
callback: F,
|
||||
binding: elements::External,
|
||||
}
|
||||
|
||||
impl<F> ImportExternalBuilder<F> where F: Invoke<elements::External> {
|
||||
/// New import to external mapping builder with callback (in chained context)
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
ImportExternalBuilder{
|
||||
callback: callback,
|
||||
@ -75,21 +85,25 @@ impl<F> ImportExternalBuilder<F> where F: Invoke<elements::External> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Function mapping with type reference
|
||||
pub fn func(mut self, index: u32) -> F::Result {
|
||||
self.binding = elements::External::Function(index);
|
||||
self.callback.invoke(self.binding)
|
||||
}
|
||||
|
||||
/// Memory mapping with specified limits
|
||||
pub fn memory(mut self, min: u32, max: Option<u32>) -> F::Result {
|
||||
self.binding = elements::External::Memory(elements::MemoryType::new(min, max));
|
||||
self.callback.invoke(self.binding)
|
||||
}
|
||||
|
||||
/// Table mapping with specified limits
|
||||
pub fn table(mut self, min: u32, max: Option<u32>) -> F::Result {
|
||||
self.binding = elements::External::Table(elements::TableType::new(min, max));
|
||||
self.callback.invoke(self.binding)
|
||||
}
|
||||
|
||||
/// Global mapping with speciifed type and mutability
|
||||
pub fn global(mut self, value_type: elements::ValueType, is_mut: bool) -> F::Result {
|
||||
self.binding = elements::External::Global(elements::GlobalType::new(value_type, is_mut));
|
||||
self.callback.invoke(self.binding)
|
||||
|
@ -1,11 +1,13 @@
|
||||
//! invoke helper
|
||||
|
||||
/// Helper trait to allow chaining
|
||||
pub trait Invoke<A> {
|
||||
type Result;
|
||||
|
||||
fn invoke(self, arg: A) -> Self::Result;
|
||||
}
|
||||
|
||||
/// Identity chain element
|
||||
pub struct Identity;
|
||||
|
||||
impl<A> Invoke<A> for Identity {
|
||||
|
@ -1,31 +1,41 @@
|
||||
use elements;
|
||||
use super::invoke::{Invoke, Identity};
|
||||
|
||||
/// Memory definition struct
|
||||
#[derive(Debug)]
|
||||
pub struct MemoryDefinition {
|
||||
/// Minimum memory size
|
||||
pub min: u32,
|
||||
/// Maximum memory size
|
||||
pub max: Option<u32>,
|
||||
/// Memory data segments (static regions)
|
||||
pub data: Vec<MemoryDataDefinition>,
|
||||
}
|
||||
|
||||
/// Memory static region entry definition
|
||||
#[derive(Debug)]
|
||||
pub struct MemoryDataDefinition {
|
||||
/// Segment initialization expression for offset
|
||||
pub offset: elements::InitExpr,
|
||||
/// Raw bytes of static region
|
||||
pub values: Vec<u8>,
|
||||
}
|
||||
|
||||
/// Memory and static regions builder
|
||||
pub struct MemoryBuilder<F=Identity> {
|
||||
callback: F,
|
||||
memory: MemoryDefinition,
|
||||
}
|
||||
|
||||
impl MemoryBuilder {
|
||||
/// New memory builder
|
||||
pub fn new() -> Self {
|
||||
MemoryBuilder::with_callback(Identity)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> MemoryBuilder<F> where F: Invoke<MemoryDefinition> {
|
||||
/// New memory builder with callback (in chained context)
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
MemoryBuilder {
|
||||
callback: callback,
|
||||
@ -33,16 +43,19 @@ impl<F> MemoryBuilder<F> where F: Invoke<MemoryDefinition> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set/override minimum size
|
||||
pub fn with_min(mut self, min: u32) -> Self {
|
||||
self.memory.min = min;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set/override maximum size
|
||||
pub fn with_max(mut self, max: Option<u32>) -> Self {
|
||||
self.memory.max = max;
|
||||
self
|
||||
}
|
||||
|
||||
/// Push new static region with initialized offset expression and raw bytes
|
||||
pub fn with_data(mut self, index: u32, values: Vec<u8>) -> Self {
|
||||
self.memory.data.push(MemoryDataDefinition {
|
||||
offset: elements::InitExpr::new(vec![
|
||||
@ -54,6 +67,7 @@ impl<F> MemoryBuilder<F> where F: Invoke<MemoryDefinition> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Finalize current builder, spawning resulting struct
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(self.memory)
|
||||
}
|
||||
|
@ -11,8 +11,15 @@ mod export;
|
||||
mod global;
|
||||
mod data;
|
||||
|
||||
pub use self::code::{
|
||||
signatures, signature, function, SignatureBuilder, SignaturesBuilder,
|
||||
FunctionBuilder, TypeRefBuilder, FuncBodyBuilder, FunctionDefinition,
|
||||
};
|
||||
pub use self::data::DataSegmentBuilder;
|
||||
pub use self::export::{export, ExportBuilder, ExportInternalBuilder};
|
||||
pub use self::global::{global, GlobalBuilder};
|
||||
pub use self::import::{import, ImportBuilder};
|
||||
pub use self::invoke::Identity;
|
||||
pub use self::memory::MemoryBuilder;
|
||||
pub use self::module::{module, from_module, ModuleBuilder};
|
||||
pub use self::code::{signatures, signature, function};
|
||||
pub use self::import::import;
|
||||
pub use self::export::export;
|
||||
pub use self::global::global;
|
||||
pub use self::table::{TableBuilder, TableDefinition, TableEntryDefinition};
|
||||
|
@ -1,31 +1,41 @@
|
||||
use elements;
|
||||
use super::invoke::{Invoke, Identity};
|
||||
|
||||
/// Table definition
|
||||
#[derive(Debug)]
|
||||
pub struct TableDefinition {
|
||||
/// Minimum length
|
||||
pub min: u32,
|
||||
/// Maximum length, if any
|
||||
pub max: Option<u32>,
|
||||
/// Element segments, if any
|
||||
pub elements: Vec<TableEntryDefinition>,
|
||||
}
|
||||
|
||||
/// Table elements entry definition
|
||||
#[derive(Debug)]
|
||||
pub struct TableEntryDefinition {
|
||||
/// Offset initialization expression
|
||||
pub offset: elements::InitExpr,
|
||||
/// Values of initialization
|
||||
pub values: Vec<u32>,
|
||||
}
|
||||
|
||||
/// Table builder
|
||||
pub struct TableBuilder<F=Identity> {
|
||||
callback: F,
|
||||
table: TableDefinition,
|
||||
}
|
||||
|
||||
impl TableBuilder {
|
||||
/// New table builder
|
||||
pub fn new() -> Self {
|
||||
TableBuilder::with_callback(Identity)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> TableBuilder<F> where F: Invoke<TableDefinition> {
|
||||
/// New table builder with callback in chained context
|
||||
pub fn with_callback(callback: F) -> Self {
|
||||
TableBuilder {
|
||||
callback: callback,
|
||||
@ -33,16 +43,19 @@ impl<F> TableBuilder<F> where F: Invoke<TableDefinition> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set/override minimum length
|
||||
pub fn with_min(mut self, min: u32) -> Self {
|
||||
self.table.min = min;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set/override maximum length
|
||||
pub fn with_max(mut self, max: Option<u32>) -> Self {
|
||||
self.table.max = max;
|
||||
self
|
||||
}
|
||||
|
||||
/// Generate initialization expression and element values on specified index
|
||||
pub fn with_element(mut self, index: u32, values: Vec<u32>) -> Self {
|
||||
self.table.elements.push(TableEntryDefinition {
|
||||
offset: elements::InitExpr::new(vec![
|
||||
@ -54,6 +67,7 @@ impl<F> TableBuilder<F> where F: Invoke<TableDefinition> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Finalize current builder spawning resulting struct
|
||||
pub fn build(self) -> F::Result {
|
||||
self.callback.invoke(self.table)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use super::{
|
||||
};
|
||||
|
||||
/// Function signature (type reference)
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Func(u32);
|
||||
|
||||
impl Func {
|
||||
@ -24,7 +24,7 @@ impl Func {
|
||||
}
|
||||
|
||||
/// Local definition inside the function body.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Local {
|
||||
count: u32,
|
||||
value_type: ValueType,
|
||||
|
@ -5,7 +5,7 @@ use super::{
|
||||
};
|
||||
|
||||
/// Global definition struct
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct GlobalType {
|
||||
content_type: ValueType,
|
||||
is_mutable: bool,
|
||||
@ -51,7 +51,7 @@ impl Serialize for GlobalType {
|
||||
}
|
||||
|
||||
/// Table entry
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TableType {
|
||||
elem_type: TableElementType,
|
||||
limits: ResizableLimits,
|
||||
@ -96,7 +96,7 @@ impl Serialize for TableType {
|
||||
}
|
||||
|
||||
/// Memory limits
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ResizableLimits {
|
||||
initial: u32,
|
||||
maximum: Option<u32>,
|
||||
@ -150,7 +150,7 @@ impl Serialize for ResizableLimits {
|
||||
}
|
||||
|
||||
/// Memory entry.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct MemoryType(ResizableLimits);
|
||||
|
||||
impl MemoryType {
|
||||
@ -181,7 +181,7 @@ impl Serialize for MemoryType {
|
||||
}
|
||||
|
||||
/// External to local binding.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum External {
|
||||
/// Binds to function with index.
|
||||
Function(u32),
|
||||
|
@ -50,7 +50,7 @@ pub trait Serialize {
|
||||
}
|
||||
|
||||
/// Deserialization/serialization error
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Error {
|
||||
/// Unexpected end of input
|
||||
UnexpectedEof,
|
||||
|
@ -10,7 +10,7 @@ use super::section::{
|
||||
const WASM_MAGIC_NUMBER: [u8; 4] = [0x00, 0x61, 0x73, 0x6d];
|
||||
|
||||
/// WebAssembly module
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Module {
|
||||
magic: u32,
|
||||
version: u32,
|
||||
@ -20,7 +20,7 @@ pub struct Module {
|
||||
impl Default for Module {
|
||||
fn default() -> Self {
|
||||
Module {
|
||||
magic: 0x6d736100,
|
||||
magic: LittleEndian::read_u32(&WASM_MAGIC_NUMBER),
|
||||
version: 1,
|
||||
sections: Vec::with_capacity(16),
|
||||
}
|
||||
@ -191,6 +191,7 @@ impl Serialize for Module {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
struct PeekSection<'a> {
|
||||
cursor: usize,
|
||||
region: &'a [u8],
|
||||
@ -389,4 +390,13 @@ mod integration_tests {
|
||||
|
||||
assert_eq!(peek_size(&buf), buf.len() - 9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn module_default_round_trip() {
|
||||
let module1 = Module::default();
|
||||
let buf = serialize(module1).expect("Serialization should succeed");
|
||||
|
||||
let module2: Module = deserialize_buffer(&buf).expect("Deserialization should succeed");
|
||||
assert_eq!(Module::default().magic, module2.magic);
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +266,7 @@ pub enum Opcode {
|
||||
F64Max,
|
||||
F64Copysign,
|
||||
|
||||
I32WarpI64,
|
||||
I32WrapI64,
|
||||
I32TruncSF32,
|
||||
I32TruncUF32,
|
||||
I32TruncSF64,
|
||||
@ -560,7 +560,7 @@ impl Deserialize for Opcode {
|
||||
0xa5 => F64Max,
|
||||
0xa6 => F64Copysign,
|
||||
|
||||
0xa7 => I32WarpI64,
|
||||
0xa7 => I32WrapI64,
|
||||
0xa8 => I32TruncSF32,
|
||||
0xa9 => I32TruncUF32,
|
||||
0xaa => I32TruncSF64,
|
||||
@ -877,7 +877,7 @@ impl Serialize for Opcode {
|
||||
F64Max => op!(writer, 0xa5),
|
||||
F64Copysign => op!(writer, 0xa6),
|
||||
|
||||
I32WarpI64 => op!(writer, 0xa7),
|
||||
I32WrapI64 => op!(writer, 0xa7),
|
||||
I32TruncSF32 => op!(writer, 0xa8),
|
||||
I32TruncUF32 => op!(writer, 0xa9),
|
||||
I32TruncSF64 => op!(writer, 0xaa),
|
||||
@ -1134,7 +1134,7 @@ impl fmt::Display for Opcode {
|
||||
F64Max => write!(f, "f64.max"),
|
||||
F64Copysign => write!(f, "f64.copysign"),
|
||||
|
||||
I32WarpI64 => write!(f, "i32.wrap/i64"),
|
||||
I32WrapI64 => write!(f, "i32.wrap/i64"),
|
||||
I32TruncSF32 => write!(f, "i32.trunc_s/f32"),
|
||||
I32TruncUF32 => write!(f, "i32.trunc_u/f32"),
|
||||
I32TruncSF64 => write!(f, "i32.trunc_s/f64"),
|
||||
|
@ -4,7 +4,7 @@ use super::{Error, Deserialize, Serialize};
|
||||
|
||||
/// Unsigned variable-length integer, limited to 32 bits,
|
||||
/// represented by at most 5 bytes that may contain padding 0x80 bytes.
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VarUint32(u32);
|
||||
|
||||
impl From<VarUint32> for usize {
|
||||
@ -74,7 +74,7 @@ impl Serialize for VarUint32 {
|
||||
|
||||
/// Unsigned variable-length integer, limited to 64 bits,
|
||||
/// represented by at most 9 bytes that may contain padding 0x80 bytes.
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VarUint64(u64);
|
||||
|
||||
impl From<VarUint64> for u64 {
|
||||
@ -130,7 +130,7 @@ impl From<u64> for VarUint64 {
|
||||
}
|
||||
|
||||
/// 7-bit unsigned integer, encoded in LEB128 (always 1 byte length)
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VarUint7(u8);
|
||||
|
||||
impl From<VarUint7> for u8 {
|
||||
@ -166,7 +166,7 @@ impl Serialize for VarUint7 {
|
||||
}
|
||||
|
||||
/// 7-bit signed integer, encoded in LEB128 (always 1 byte length)
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VarInt7(i8);
|
||||
|
||||
impl From<VarInt7> for i8 {
|
||||
@ -207,7 +207,7 @@ impl Serialize for VarInt7 {
|
||||
}
|
||||
|
||||
/// 32-bit signed integer, encoded in LEB128 (can be 1-5 bytes length)
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VarInt32(i32);
|
||||
|
||||
impl From<VarInt32> for i32 {
|
||||
@ -271,7 +271,7 @@ impl Serialize for VarInt32 {
|
||||
}
|
||||
|
||||
/// 64-bit signed integer, encoded in LEB128 (can be 1-9 bytes length)
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VarInt64(i64);
|
||||
|
||||
impl From<VarInt64> for i64 {
|
||||
@ -335,7 +335,7 @@ impl Serialize for VarInt64 {
|
||||
}
|
||||
|
||||
/// 32-bit unsigned integer, encoded in little endian
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Uint32(u32);
|
||||
|
||||
impl Deserialize for Uint32 {
|
||||
@ -371,7 +371,7 @@ impl From<u32> for Uint32 {
|
||||
}
|
||||
|
||||
/// 64-bit unsigned integer, encoded in little endian
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Uint64(u64);
|
||||
|
||||
impl Deserialize for Uint64 {
|
||||
@ -408,7 +408,7 @@ impl From<Uint64> for u64 {
|
||||
|
||||
|
||||
/// VarUint1, 1-bit value (0/1)
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct VarUint1(bool);
|
||||
|
||||
impl From<VarUint1> for bool {
|
||||
@ -476,6 +476,7 @@ impl Serialize for String {
|
||||
|
||||
/// List for reading sequence of elements typed `T`, given
|
||||
/// they are preceded by length (serialized as VarUint32)
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CountedList<T: Deserialize>(Vec<T>);
|
||||
|
||||
impl<T: Deserialize> CountedList<T> {
|
||||
@ -496,6 +497,7 @@ impl<T: Deserialize> Deserialize for CountedList<T> where T::Error: From<Error>
|
||||
|
||||
/// Helper struct to write payload which is preceded by
|
||||
/// it's own length in bytes.
|
||||
#[derive(Debug)]
|
||||
pub struct CountedWriter<'a, W: 'a + io::Write> {
|
||||
writer: &'a mut W,
|
||||
data: Vec<u8>,
|
||||
@ -541,6 +543,7 @@ impl<'a, W: 'a + io::Write> io::Write for CountedWriter<'a, W> {
|
||||
|
||||
/// Helper struct to write series of `T` preceded by the length of the sequence
|
||||
/// serialized as VarUint32
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CountedListWriter<I: Serialize<Error=::elements::Error>, T: IntoIterator<Item=I>>(pub usize, pub T);
|
||||
|
||||
impl<I: Serialize<Error=::elements::Error>, T: IntoIterator<Item=I>> Serialize for CountedListWriter<I, T> {
|
||||
|
@ -24,7 +24,7 @@ use super::{
|
||||
use super::types::Type;
|
||||
|
||||
/// Section in the WebAssembly module.
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Section {
|
||||
/// Section is unparsed.
|
||||
Unparsed {
|
||||
@ -181,7 +181,7 @@ impl Serialize for Section {
|
||||
}
|
||||
|
||||
/// Custom section
|
||||
#[derive(Clone)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CustomSection {
|
||||
name: String,
|
||||
payload: Vec<u8>,
|
||||
@ -241,7 +241,7 @@ impl Serialize for CustomSection {
|
||||
}
|
||||
|
||||
/// Section with type declarations
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct TypeSection(Vec<Type>);
|
||||
|
||||
impl TypeSection {
|
||||
@ -351,7 +351,7 @@ impl Serialize for ImportSection {
|
||||
}
|
||||
|
||||
/// Section with function signatures definition.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct FunctionSection(Vec<Func>);
|
||||
|
||||
impl FunctionSection {
|
||||
@ -403,7 +403,7 @@ impl Serialize for FunctionSection {
|
||||
}
|
||||
|
||||
/// Section with table definition (currently only one is allowed).
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct TableSection(Vec<TableType>);
|
||||
|
||||
impl TableSection {
|
||||
@ -451,7 +451,7 @@ impl Serialize for TableSection {
|
||||
}
|
||||
|
||||
/// Section with table definition (currently only one entry is allowed).
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct MemorySection(Vec<MemoryType>);
|
||||
|
||||
impl MemorySection {
|
||||
@ -499,7 +499,7 @@ impl Serialize for MemorySection {
|
||||
}
|
||||
|
||||
/// Globals definition section.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct GlobalSection(Vec<GlobalEntry>);
|
||||
|
||||
impl GlobalSection {
|
||||
@ -595,7 +595,7 @@ impl Serialize for ExportSection {
|
||||
}
|
||||
|
||||
/// Section with function bodies of the module.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct CodeSection(Vec<FuncBody>);
|
||||
|
||||
impl CodeSection {
|
||||
@ -643,7 +643,7 @@ impl Serialize for CodeSection {
|
||||
}
|
||||
|
||||
/// Element entries section.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct ElementSection(Vec<ElementSegment>);
|
||||
|
||||
impl ElementSection {
|
||||
@ -691,7 +691,7 @@ impl Serialize for ElementSection {
|
||||
}
|
||||
|
||||
/// Data entries definitions.
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct DataSection(Vec<DataSegment>);
|
||||
|
||||
impl DataSection {
|
||||
|
@ -68,7 +68,7 @@ impl Serialize for ElementSegment {
|
||||
}
|
||||
|
||||
/// Data segment definition.
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DataSegment {
|
||||
index: u32,
|
||||
offset: InitExpr,
|
||||
|
@ -319,7 +319,7 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
||||
&Opcode::F64Max => self.run_max::<f64>(context),
|
||||
&Opcode::F64Copysign => self.run_copysign::<f64>(context),
|
||||
|
||||
&Opcode::I32WarpI64 => self.run_wrap::<i64, i32>(context),
|
||||
&Opcode::I32WrapI64 => self.run_wrap::<i64, i32>(context),
|
||||
&Opcode::I32TruncSF32 => self.run_trunc_to_int::<f32, i32, i32>(context),
|
||||
&Opcode::I32TruncUF32 => self.run_trunc_to_int::<f32, u32, i32>(context),
|
||||
&Opcode::I32TruncSF64 => self.run_trunc_to_int::<f64, i32, i32>(context),
|
||||
|
@ -281,7 +281,7 @@ impl Validator {
|
||||
F64Max => Validator::validate_binop(context, ValueType::F64),
|
||||
F64Copysign => Validator::validate_binop(context, ValueType::F64),
|
||||
|
||||
I32WarpI64 => Validator::validate_cvtop(context, ValueType::I64, ValueType::I32),
|
||||
I32WrapI64 => Validator::validate_cvtop(context, ValueType::I64, ValueType::I32),
|
||||
I32TruncSF32 => Validator::validate_cvtop(context, ValueType::F32, ValueType::I32),
|
||||
I32TruncUF32 => Validator::validate_cvtop(context, ValueType::F32, ValueType::I32),
|
||||
I32TruncSF64 => Validator::validate_cvtop(context, ValueType::F64, ValueType::I32),
|
||||
|
Loading…
x
Reference in New Issue
Block a user