From bfa2e56bb9057255bc6320597ea7641f198a46f5 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Mon, 3 Apr 2017 19:51:18 +0300 Subject: [PATCH] ops initial --- src/elements/func.rs | 37 ++++- src/elements/ops.rs | 298 ++++++++++++++++++++++++++++++++++++- src/elements/primitives.rs | 71 +++++++++ src/elements/section.rs | 16 ++ src/elements/types.rs | 15 ++ 5 files changed, 433 insertions(+), 4 deletions(-) diff --git a/src/elements/func.rs b/src/elements/func.rs index c080e92..f72c355 100644 --- a/src/elements/func.rs +++ b/src/elements/func.rs @@ -1,5 +1,8 @@ use std::io; -use super::{Deserialize, Error, ValueType, VarUint32, CountedList, Opcodes}; +use super::{ + Deserialize, Error, ValueType, VarUint32, CountedList, Opcodes, + Serialize, CountedWriter, CountedListWriter, +}; /// Function signature (type reference) pub struct Func(u32); @@ -32,6 +35,16 @@ impl Deserialize for Local { } } +impl Serialize for Local { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + VarUint32::from(self.count).serialize(writer)?; + self.value_type.serialize(writer)?; + Ok(()) + } +} + pub struct FuncBody { locals: Vec, opcodes: Opcodes, @@ -52,4 +65,26 @@ impl Deserialize for FuncBody { let opcodes = Opcodes::deserialize(reader)?; Ok(FuncBody { locals: locals, opcodes: opcodes }) } +} + +impl Serialize for FuncBody { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + let mut counted_writer = CountedWriter::new(writer); + + let data = self.locals; + let counted_list = CountedListWriter::( + data.len(), + data.into_iter().map(Into::into), + ); + counted_list.serialize(&mut counted_writer)?; + + let code = self.opcodes; + code.serialize(&mut counted_writer)?; + + counted_writer.done()?; + + Ok(()) + } } \ No newline at end of file diff --git a/src/elements/ops.rs b/src/elements/ops.rs index 7a0bf0e..13b97cf 100644 --- a/src/elements/ops.rs +++ b/src/elements/ops.rs @@ -2,7 +2,7 @@ use std::io; use super::{ Serialize, Deserialize, Error, VarUint7, VarUint1, VarUint32, CountedList, BlockType, - Uint32, VarUint64, Uint64 + Uint32, VarUint64, Uint64, CountedListWriter }; pub struct Opcodes(Vec); @@ -566,8 +566,300 @@ impl Serialize for Opcode { Block(block_type, ops) => op!(writer, 0x02, { block_type.serialize(writer)?; ops.serialize(writer)?; - }), - End => op!(writer, 0x0b), + }), + Loop(block_type, ops) => op!(writer, 0x03, { + block_type.serialize(writer)?; + ops.serialize(writer)?; + }), + If(block_type, ops) => op!(writer, 0x04, { + block_type.serialize(writer)?; + ops.serialize(writer)?; + }), + Else => op!(writer, 0x05), + End => op!(writer, 0x0b), + Br(idx) => op!(writer, 0x0c, { + VarUint32::from(idx).serialize(writer)?; + }), + BrIf(idx) => op!(writer, 0x0d, { + VarUint32::from(idx).serialize(writer)?; + }), + BrTable(table, default) => op!(writer, 0x0e, { + let list_writer = CountedListWriter::( + table.len(), + table.into_iter().map(Into::into), + ); + list_writer.serialize(writer)?; + VarUint32::from(default).serialize(writer)?; + }), + Return => op!(writer, 0x0f), + Call(index) => op!(writer, 0x10, { + VarUint32::from(index).serialize(writer)?; + }), + CallIndirect(index, reserved) => op!(writer, 0x11, { + VarUint32::from(index).serialize(writer)?; + VarUint1::from(reserved).serialize(writer)?; + }), + Drop => op!(writer, 0x1a), + Select => op!(writer, 0x1b), + GetLocal(index) => op!(writer, 0x20, { + VarUint32::from(index).serialize(writer)?; + }), + SetLocal(index) => op!(writer, 0x21, { + VarUint32::from(index).serialize(writer)?; + }), + TeeLocal(index) => op!(writer, 0x22, { + VarUint32::from(index).serialize(writer)?; + }), + GetGlobal(index) => op!(writer, 0x23, { + VarUint32::from(index).serialize(writer)?; + }), + SetGlobal(index) => op!(writer, 0x24, { + VarUint32::from(index).serialize(writer)?; + }), + I32Load(from, to) => op!(writer, 0x28, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Load(from, to) => op!(writer, 0x29, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + F32Load(from, to) => op!(writer, 0x2a, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + F64Load(from, to) => op!(writer, 0x2b, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I32Load8S(from, to) => op!(writer, 0x2c, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I32Load8U(from, to) => op!(writer, 0x2d, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I32Load16S(from, to) => op!(writer, 0x2e, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I32Load16U(from, to) => op!(writer, 0x2f, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Load8S(from, to) => op!(writer, 0x30, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Load8U(from, to) => op!(writer, 0x31, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Load16S(from, to) => op!(writer, 0x32, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Load16U(from, to) => op!(writer, 0x33, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Load32S(from, to) => op!(writer, 0x34, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Load32U(from, to) => op!(writer, 0x35, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I32Store(from, to) => op!(writer, 0x36, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Store(from, to) => op!(writer, 0x37, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + F32Store(from, to) => op!(writer, 0x38, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + F64Store(from, to) => op!(writer, 0x39, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I32Store8(from, to) => op!(writer, 0x3a, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I32Store16(from, to) => op!(writer, 0x3b, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Store8(from, to) => op!(writer, 0x3c, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Store16(from, to) => op!(writer, 0x3d, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + I64Store32(from, to) => op!(writer, 0x3e, { + VarUint32::from(from).serialize(writer)?; + VarUint32::from(to).serialize(writer)?; + }), + CurrentMemory(flag) => op!(writer, 0x3f, { + VarUint1::from(flag).serialize(writer)?; + }), + GrowMemory(flag) => op!(writer, 0x40, { + VarUint1::from(flag).serialize(writer)?; + }), + I32Const(def) => op!(writer, 0x41, { + VarUint32::from(def).serialize(writer)?; + }), + I64Const(def) => op!(writer, 0x42, { + VarUint64::from(def).serialize(writer)?; + }), + F32Const(def) => op!(writer, 0x43, { + Uint32::from(def).serialize(writer)?; + }), + F64Const(def) => op!(writer, 0x44, { + Uint64::from(def).serialize(writer)?; + }), + + // 0x45 => I32Eqz, + // 0x46 => I32Eq, + // 0x47 => I32Ne, + // 0x48 => I32LtS, + // 0x49 => I32LtU, + // 0x4a => I32GtS, + // 0x4b => I32GtU, + // 0x4c => I32LeS, + // 0x4d => I32LeU, + // 0x4e => I32GeS, + // 0x4f => I32GeU, + + // 0x50 => I64Eqz, + // 0x51 => I64Eq, + // 0x52 => I64Ne, + // 0x53 => I64LtS, + // 0x54 => I64LtU, + // 0x55 => I64GtS, + // 0x56 => I64GtU, + // 0x57 => I64LeS, + // 0x58 => I64LeU, + // 0x59 => I64GeS, + // 0x5a => I64GeU, + + // 0x5b => F32Eq, + // 0x5c => F32Ne, + // 0x5d => F32Lt, + // 0x5e => F32Gt, + // 0x5f => F32Le, + // 0x60 => F32Ge, + + // 0x61 => F64Eq, + // 0x62 => F64Ne, + // 0x63 => F64Lt, + // 0x64 => F64Gt, + // 0x65 => F64Le, + // 0x66 => F64Ge, + + // 0x67 => I32Clz, + // 0x68 => I32Ctz, + // 0x69 => I32Popcnt, + // 0x6a => I32Add, + // 0x6b => I32Sub, + // 0x6c => I32Mul, + // 0x6d => I32DivS, + // 0x6e => I32DivU, + // 0x6f => I32RemS, + // 0x70 => I32RemU, + // 0x71 => I32And, + // 0x72 => I32Or, + // 0x73 => I32Xor, + // 0x74 => I32Shl, + // 0x75 => I32ShlS, + // 0x76 => I32ShrU, + // 0x77 => I32Rotl, + // 0x78 => I32Rotr, + + // 0x79 => I64Clz, + // 0x7a => I64Ctz, + // 0x7b => I64Popcnt, + // 0x7c => I64Add, + // 0x7d => I64Sub, + // 0x7e => I64Mul, + // 0x7f => I64DivS, + // 0x80 => I64DivU, + // 0x81 => I64RemS, + // 0x82 => I64RemU, + // 0x83 => I64And, + // 0x84 => I64Or, + // 0x85 => I64Xor, + // 0x86 => I64Shl, + // 0x87 => I64ShrS, + // 0x88 => I64ShrU, + // 0x89 => I64Rotl, + // 0x8a => I64Rotr, + // 0x8b => F32Abs, + // 0x8c => F32Neg, + // 0x8d => F32Ceil, + // 0x8e => F32Floor, + // 0x8f => F32Trunc, + // 0x90 => F32Nearest, + // 0x91 => F32Sqrt, + // 0x92 => F32Add, + // 0x93 => F32Sub, + // 0x94 => F32Mul, + // 0x95 => F32Div, + // 0x96 => F32Min, + // 0x97 => F32Max, + // 0x98 => F32Copysign, + // 0x99 => F64Abs, + // 0x9a => F64Neg, + // 0x9b => F64Ceil, + // 0x9c => F64Floor, + // 0x9d => F64Trunc, + // 0x9e => F64Nearest, + // 0x9f => F64Sqrt, + // 0xa0 => F64Add, + // 0xa1 => F64Sub, + // 0xa2 => F64Mul, + // 0xa3 => F64Div, + // 0xa4 => F64Min, + // 0xa5 => F64Max, + // 0xa6 => F64Copysign, + + // 0xa7 => I32WarpI64, + // 0xa8 => I32TruncSF32, + // 0xa9 => I32TruncUF32, + // 0xaa => I32TruncSF64, + // 0xab => I32TruncUF64, + // 0xac => I64ExtendSI32, + // 0xad => I64ExtendUI32, + // 0xae => I64TruncSF32, + // 0xaf => I64TruncUF32, + // 0xb0 => I64TruncSF64, + // 0xb1 => I64TruncUF64, + // 0xb2 => F32ConvertSI32, + // 0xb3 => F32ConvertUI32, + // 0xb4 => F32ConvertSI64, + // 0xb5 => F32ConvertUI64, + // 0xb6 => F32DemoteF64, + // 0xb7 => F64ConvertSI32, + // 0xb8 => F64ConvertUI32, + // 0xb9 => F64ConvertSI64, + // 0xba => F64ConvertUI64, + // 0xbb => F64PromoteF32, + + // 0xbc => I32ReinterpretF32, + // 0xbd => I64ReinterpretF64, + // 0xbe => F32ReinterpretI32, + // 0xbf => F64ReinterpretI64, + + + // End => op!(writer, 0x0b), _ => unreachable!(), } diff --git a/src/elements/primitives.rs b/src/elements/primitives.rs index 020d210..ca3cb37 100644 --- a/src/elements/primitives.rs +++ b/src/elements/primitives.rs @@ -97,6 +97,30 @@ impl Deserialize for VarUint64 { } } +impl Serialize for VarUint64 { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + let mut buf = [0u8; 1]; + let mut v = self.0; + while v >= 0x80 { + buf[0] = ((v & 0xff) as u8) | 0x80; + writer.write_all(&buf[..])?; + v >>= 7; + } + buf[0] = (v & 0xff) as u8; + writer.write_all(&buf[..])?; + + Ok(()) + } +} + +impl From for VarUint64 { + fn from(u: u64) -> VarUint64 { + VarUint64(u) + } +} + #[derive(Copy, Clone)] pub struct VarUint7(u8); @@ -176,6 +200,20 @@ impl From for u32 { } } +impl Serialize for Uint32 { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + let mut buf = [0u8; 4]; + LittleEndian::write_u32(&mut buf, self.0); + writer.write_all(&buf)?; + Ok(()) + } +} + +impl From for Uint32 { + fn from(u: u32) -> Self { Uint32(u) } +} #[derive(Copy, Clone)] pub struct Uint64(u64); @@ -191,12 +229,28 @@ impl Deserialize for Uint64 { } } +impl Serialize for Uint64 { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + let mut buf = [0u8; 8]; + LittleEndian::write_u64(&mut buf, self.0); + writer.write_all(&buf)?; + Ok(()) + } +} + +impl From for Uint64 { + fn from(u: u64) -> Self { Uint64(u) } +} + impl From for u64 { fn from(var: Uint64) -> u64 { var.0 } } + #[derive(Copy, Clone)] pub struct VarUint1(bool); @@ -206,6 +260,12 @@ impl From for bool { } } +impl From for VarUint1 { + fn from(b: bool) -> Self { + VarUint1(b) + } +} + impl Deserialize for VarUint1 { type Error = Error; @@ -217,6 +277,17 @@ impl Deserialize for VarUint1 { } } +impl Serialize for VarUint1 { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + writer.write_all(&[ + if self.0 { 1u8 } else { 0u8 } + ])?; + Ok(()) + } +} + impl Deserialize for String { type Error = Error; diff --git a/src/elements/section.rs b/src/elements/section.rs index 7109e86..b340747 100644 --- a/src/elements/section.rs +++ b/src/elements/section.rs @@ -254,6 +254,22 @@ impl Deserialize for CodeSection { } } +impl Serialize for CodeSection { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + let mut counted_writer = CountedWriter::new(writer); + let data = self.0; + let counted_list = CountedListWriter::( + data.len(), + data.into_iter().map(Into::into), + ); + counted_list.serialize(&mut counted_writer)?; + counted_writer.done()?; + Ok(()) + } +} + pub struct ElementSection(Vec); impl ElementSection { diff --git a/src/elements/types.rs b/src/elements/types.rs index 7422f7e..d3db2d5 100644 --- a/src/elements/types.rs +++ b/src/elements/types.rs @@ -37,6 +37,21 @@ impl Deserialize for ValueType { } } +impl Serialize for ValueType { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + let val: VarInt7 = match self { + ValueType::I32 => -0x01, + ValueType::I64 => -0x02, + ValueType::F32 => -0x03, + ValueType::F64 => -0x04, + }.into(); + val.serialize(writer)?; + Ok(()) + } +} + #[derive(Clone, Copy, PartialEq, Debug)] pub enum BlockType { Value(ValueType),