From 8c5ef589bc6e21d074df502226a1008a63aa23cd Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 26 Aug 2018 15:48:19 -0700 Subject: [PATCH] Add support for atomic instructions This commit adds support for the currently proposed atomic instructions in the wasm spec. The implementaiton matches what LLVM currently has implemented, and while this may be tweaked over time it should be good enough to work with LLVM today! https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md --- src/elements/import_entry.rs | 14 +- src/elements/module.rs | 3 +- src/elements/ops.rs | 414 +++++++++++++++++++++++++++++++++++ 3 files changed, 425 insertions(+), 6 deletions(-) diff --git a/src/elements/import_entry.rs b/src/elements/import_entry.rs index 41de029..7708d3a 100644 --- a/src/elements/import_entry.rs +++ b/src/elements/import_entry.rs @@ -1,7 +1,7 @@ use io; use std::string::String; use super::{ - Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint32, VarUint1, + Deserialize, Serialize, Error, VarUint7, VarInt7, VarUint32, VarUint1, Uint8, ValueType, TableElementType }; @@ -101,6 +101,7 @@ impl Serialize for TableType { pub struct ResizableLimits { initial: u32, maximum: Option, + flags: u8, } impl ResizableLimits { @@ -109,21 +110,24 @@ impl ResizableLimits { ResizableLimits { initial: min, maximum: max, + flags: 0, } } /// Initial size pub fn initial(&self) -> u32 { self.initial } /// Maximum size pub fn maximum(&self) -> Option { self.maximum } + /// Whether or not this is a shared array buffer + pub fn shared(&self) -> bool { self.flags & 0x2 != 0 } } impl Deserialize for ResizableLimits { type Error = Error; fn deserialize(reader: &mut R) -> Result { - let has_max = VarUint1::deserialize(reader)?; + let flags: u8 = Uint8::deserialize(reader)?.into(); let initial = VarUint32::deserialize(reader)?; - let maximum = if has_max.into() { + let maximum = if flags & 0x1 != 0 { Some(VarUint32::deserialize(reader)?.into()) } else { None @@ -132,6 +136,7 @@ impl Deserialize for ResizableLimits { Ok(ResizableLimits { initial: initial.into(), maximum: maximum, + flags, }) } } @@ -141,7 +146,8 @@ impl Serialize for ResizableLimits { fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { let max = self.maximum; - VarUint1::from(max.is_some()).serialize(writer)?; + let flags = self.flags & !0x1 | (if max.is_some() { 0x1 } else { 0x0 }); + Uint8::from(flags).serialize(writer)?; VarUint32::from(self.initial).serialize(writer)?; if let Some(val) = max { VarUint32::from(val).serialize(writer)?; diff --git a/src/elements/module.rs b/src/elements/module.rs index f17c202..31f1192 100644 --- a/src/elements/module.rs +++ b/src/elements/module.rs @@ -702,8 +702,7 @@ mod integration_tests { } #[test] - #[should_panic] - fn wrong_varuint1_case() { + fn varuint1_case() { let _module = deserialize_file("./res/cases/v1/varuint1_1.wasm") .expect("Maybe shouldn't be deserialized"); } diff --git a/src/elements/ops.rs b/src/elements/ops.rs index 05a24f6..56d6829 100644 --- a/src/elements/ops.rs +++ b/src/elements/ops.rs @@ -294,6 +294,88 @@ pub enum Instruction { I64ReinterpretF64, F32ReinterpretI32, F64ReinterpretI64, + + AtomicWake(MemArg), + I32AtomicWait(MemArg), + I64AtomicWait(MemArg), + + I32AtomicLoad(MemArg), + I64AtomicLoad(MemArg), + I32AtomicLoad8u(MemArg), + I32AtomicLoad16u(MemArg), + I64AtomicLoad8u(MemArg), + I64AtomicLoad16u(MemArg), + I64AtomicLoad32u(MemArg), + I32AtomicStore(MemArg), + I64AtomicStore(MemArg), + I32AtomicStore8u(MemArg), + I32AtomicStore16u(MemArg), + I64AtomicStore8u(MemArg), + I64AtomicStore16u(MemArg), + I64AtomicStore32u(MemArg), + + I32AtomicRmwAdd(MemArg), + I64AtomicRmwAdd(MemArg), + I32AtomicRmwAdd8u(MemArg), + I32AtomicRmwAdd16u(MemArg), + I64AtomicRmwAdd8u(MemArg), + I64AtomicRmwAdd16u(MemArg), + I64AtomicRmwAdd32u(MemArg), + + I32AtomicRmwSub(MemArg), + I64AtomicRmwSub(MemArg), + I32AtomicRmwSub8u(MemArg), + I32AtomicRmwSub16u(MemArg), + I64AtomicRmwSub8u(MemArg), + I64AtomicRmwSub16u(MemArg), + I64AtomicRmwSub32u(MemArg), + + I32AtomicRmwAnd(MemArg), + I64AtomicRmwAnd(MemArg), + I32AtomicRmwAnd8u(MemArg), + I32AtomicRmwAnd16u(MemArg), + I64AtomicRmwAnd8u(MemArg), + I64AtomicRmwAnd16u(MemArg), + I64AtomicRmwAnd32u(MemArg), + + I32AtomicRmwOr(MemArg), + I64AtomicRmwOr(MemArg), + I32AtomicRmwOr8u(MemArg), + I32AtomicRmwOr16u(MemArg), + I64AtomicRmwOr8u(MemArg), + I64AtomicRmwOr16u(MemArg), + I64AtomicRmwOr32u(MemArg), + + I32AtomicRmwXor(MemArg), + I64AtomicRmwXor(MemArg), + I32AtomicRmwXor8u(MemArg), + I32AtomicRmwXor16u(MemArg), + I64AtomicRmwXor8u(MemArg), + I64AtomicRmwXor16u(MemArg), + I64AtomicRmwXor32u(MemArg), + + I32AtomicRmwXchg(MemArg), + I64AtomicRmwXchg(MemArg), + I32AtomicRmwXchg8u(MemArg), + I32AtomicRmwXchg16u(MemArg), + I64AtomicRmwXchg8u(MemArg), + I64AtomicRmwXchg16u(MemArg), + I64AtomicRmwXchg32u(MemArg), + + I32AtomicRmwCmpxchg(MemArg), + I64AtomicRmwCmpxchg(MemArg), + I32AtomicRmwCmpxchg8u(MemArg), + I32AtomicRmwCmpxchg16u(MemArg), + I64AtomicRmwCmpxchg8u(MemArg), + I64AtomicRmwCmpxchg16u(MemArg), + I64AtomicRmwCmpxchg32u(MemArg), +} + +#[derive(Clone, Debug, PartialEq)] +#[allow(missing_docs)] +pub struct MemArg { + pub align: u8, + pub offset: u32, } impl Instruction { @@ -495,6 +577,82 @@ pub mod opcodes { pub const I64REINTERPRETF64: u8 = 0xbd; pub const F32REINTERPRETI32: u8 = 0xbe; pub const F64REINTERPRETI64: u8 = 0xbf; + + pub const ATOMIC_PREFIX: u8 = 0xfe; + pub const ATOMIC_WAKE: u8 = 0x00; + pub const I32_ATOMIC_WAIT: u8 = 0x01; + pub const I64_ATOMIC_WAIT: u8 = 0x02; + + pub const I32_ATOMIC_LOAD: u8 = 0x10; + pub const I64_ATOMIC_LOAD: u8 = 0x11; + pub const I32_ATOMIC_LOAD8U: u8 = 0x12; + pub const I32_ATOMIC_LOAD16U: u8 = 0x13; + pub const I64_ATOMIC_LOAD8U: u8 = 0x14; + pub const I64_ATOMIC_LOAD16U: u8 = 0x15; + pub const I64_ATOMIC_LOAD32U: u8 = 0x16; + pub const I32_ATOMIC_STORE: u8 = 0x17; + pub const I64_ATOMIC_STORE: u8 = 0x18; + pub const I32_ATOMIC_STORE8U: u8 = 0x19; + pub const I32_ATOMIC_STORE16U: u8 = 0x1a; + pub const I64_ATOMIC_STORE8U: u8 = 0x1b; + pub const I64_ATOMIC_STORE16U: u8 = 0x1c; + pub const I64_ATOMIC_STORE32U: u8 = 0x1d; + + pub const I32_ATOMIC_RMW_ADD: u8 = 0x1e; + pub const I64_ATOMIC_RMW_ADD: u8 = 0x1f; + pub const I32_ATOMIC_RMW_ADD8U: u8 = 0x20; + pub const I32_ATOMIC_RMW_ADD16U: u8 = 0x21; + pub const I64_ATOMIC_RMW_ADD8U: u8 = 0x22; + pub const I64_ATOMIC_RMW_ADD16U: u8 = 0x23; + pub const I64_ATOMIC_RMW_ADD32U: u8 = 0x24; + + pub const I32_ATOMIC_RMW_SUB: u8 = 0x25; + pub const I64_ATOMIC_RMW_SUB: u8 = 0x26; + pub const I32_ATOMIC_RMW_SUB8U: u8 = 0x27; + pub const I32_ATOMIC_RMW_SUB16U: u8 = 0x28; + pub const I64_ATOMIC_RMW_SUB8U: u8 = 0x29; + pub const I64_ATOMIC_RMW_SUB16U: u8 = 0x2a; + pub const I64_ATOMIC_RMW_SUB32U: u8 = 0x2b; + + pub const I32_ATOMIC_RMW_AND: u8 = 0x2c; + pub const I64_ATOMIC_RMW_AND: u8 = 0x2d; + pub const I32_ATOMIC_RMW_AND8U: u8 = 0x2e; + pub const I32_ATOMIC_RMW_AND16U: u8 = 0x2f; + pub const I64_ATOMIC_RMW_AND8U: u8 = 0x30; + pub const I64_ATOMIC_RMW_AND16U: u8 = 0x31; + pub const I64_ATOMIC_RMW_AND32U: u8 = 0x32; + + pub const I32_ATOMIC_RMW_OR: u8 = 0x33; + pub const I64_ATOMIC_RMW_OR: u8 = 0x34; + pub const I32_ATOMIC_RMW_OR8U: u8 = 0x35; + pub const I32_ATOMIC_RMW_OR16U: u8 = 0x36; + pub const I64_ATOMIC_RMW_OR8U: u8 = 0x37; + pub const I64_ATOMIC_RMW_OR16U: u8 = 0x38; + pub const I64_ATOMIC_RMW_OR32U: u8 = 0x39; + + pub const I32_ATOMIC_RMW_XOR: u8 = 0x3a; + pub const I64_ATOMIC_RMW_XOR: u8 = 0x3b; + pub const I32_ATOMIC_RMW_XOR8U: u8 = 0x3c; + pub const I32_ATOMIC_RMW_XOR16U: u8 = 0x3d; + pub const I64_ATOMIC_RMW_XOR8U: u8 = 0x3e; + pub const I64_ATOMIC_RMW_XOR16U: u8 = 0x3f; + pub const I64_ATOMIC_RMW_XOR32U: u8 = 0x40; + + pub const I32_ATOMIC_RMW_XCHG: u8 = 0x41; + pub const I64_ATOMIC_RMW_XCHG: u8 = 0x42; + pub const I32_ATOMIC_RMW_XCHG8U: u8 = 0x43; + pub const I32_ATOMIC_RMW_XCHG16U: u8 = 0x44; + pub const I64_ATOMIC_RMW_XCHG8U: u8 = 0x45; + pub const I64_ATOMIC_RMW_XCHG16U: u8 = 0x46; + pub const I64_ATOMIC_RMW_XCHG32U: u8 = 0x47; + + pub const I32_ATOMIC_RMW_CMPXCHG: u8 = 0x48; + pub const I64_ATOMIC_RMW_CMPXCHG: u8 = 0x49; + pub const I32_ATOMIC_RMW_CMPXCHG8U: u8 = 0x4a; + pub const I32_ATOMIC_RMW_CMPXCHG16U: u8 = 0x4b; + pub const I64_ATOMIC_RMW_CMPXCHG8U: u8 = 0x4c; + pub const I64_ATOMIC_RMW_CMPXCHG16U: u8 = 0x4d; + pub const I64_ATOMIC_RMW_CMPXCHG32U: u8 = 0x4e; } impl Deserialize for Instruction { @@ -787,11 +945,100 @@ impl Deserialize for Instruction { F32REINTERPRETI32 => F32ReinterpretI32, F64REINTERPRETI64 => F64ReinterpretI64, + ATOMIC_PREFIX => return deserialize_atomic(reader), + _ => { return Err(Error::UnknownOpcode(val)); } } ) } } +fn deserialize_atomic(reader: &mut R) -> Result { + use self::Instruction::*; + use self::opcodes::*; + + let val: u8 = Uint8::deserialize(reader)?.into(); + let mem = MemArg::deserialize(reader)?; + Ok(match val { + ATOMIC_WAKE => AtomicWake(mem), + I32_ATOMIC_WAIT => I32AtomicWait(mem), + I64_ATOMIC_WAIT => I64AtomicWait(mem), + + I32_ATOMIC_LOAD => I32AtomicLoad(mem), + I64_ATOMIC_LOAD => I64AtomicLoad(mem), + I32_ATOMIC_LOAD8U => I32AtomicLoad8u(mem), + I32_ATOMIC_LOAD16U => I32AtomicLoad16u(mem), + I64_ATOMIC_LOAD8U => I64AtomicLoad8u(mem), + I64_ATOMIC_LOAD16U => I64AtomicLoad16u(mem), + I64_ATOMIC_LOAD32U => I64AtomicLoad32u(mem), + I32_ATOMIC_STORE => I32AtomicStore(mem), + I64_ATOMIC_STORE => I64AtomicStore(mem), + I32_ATOMIC_STORE8U => I32AtomicStore8u(mem), + I32_ATOMIC_STORE16U => I32AtomicStore16u(mem), + I64_ATOMIC_STORE8U => I64AtomicStore8u(mem), + I64_ATOMIC_STORE16U => I64AtomicStore16u(mem), + I64_ATOMIC_STORE32U => I64AtomicStore32u(mem), + + I32_ATOMIC_RMW_ADD => I32AtomicRmwAdd(mem), + I64_ATOMIC_RMW_ADD => I64AtomicRmwAdd(mem), + I32_ATOMIC_RMW_ADD8U => I32AtomicRmwAdd8u(mem), + I32_ATOMIC_RMW_ADD16U => I32AtomicRmwAdd16u(mem), + I64_ATOMIC_RMW_ADD8U => I64AtomicRmwAdd8u(mem), + I64_ATOMIC_RMW_ADD16U => I64AtomicRmwAdd16u(mem), + I64_ATOMIC_RMW_ADD32U => I64AtomicRmwAdd32u(mem), + + I32_ATOMIC_RMW_SUB => I32AtomicRmwSub(mem), + I64_ATOMIC_RMW_SUB => I64AtomicRmwSub(mem), + I32_ATOMIC_RMW_SUB8U => I32AtomicRmwSub8u(mem), + I32_ATOMIC_RMW_SUB16U => I32AtomicRmwSub16u(mem), + I64_ATOMIC_RMW_SUB8U => I64AtomicRmwSub8u(mem), + I64_ATOMIC_RMW_SUB16U => I64AtomicRmwSub16u(mem), + I64_ATOMIC_RMW_SUB32U => I64AtomicRmwSub32u(mem), + + I32_ATOMIC_RMW_OR => I32AtomicRmwOr(mem), + I64_ATOMIC_RMW_OR => I64AtomicRmwOr(mem), + I32_ATOMIC_RMW_OR8U => I32AtomicRmwOr8u(mem), + I32_ATOMIC_RMW_OR16U => I32AtomicRmwOr16u(mem), + I64_ATOMIC_RMW_OR8U => I64AtomicRmwOr8u(mem), + I64_ATOMIC_RMW_OR16U => I64AtomicRmwOr16u(mem), + I64_ATOMIC_RMW_OR32U => I64AtomicRmwOr32u(mem), + + I32_ATOMIC_RMW_XOR => I32AtomicRmwXor(mem), + I64_ATOMIC_RMW_XOR => I64AtomicRmwXor(mem), + I32_ATOMIC_RMW_XOR8U => I32AtomicRmwXor8u(mem), + I32_ATOMIC_RMW_XOR16U => I32AtomicRmwXor16u(mem), + I64_ATOMIC_RMW_XOR8U => I64AtomicRmwXor8u(mem), + I64_ATOMIC_RMW_XOR16U => I64AtomicRmwXor16u(mem), + I64_ATOMIC_RMW_XOR32U => I64AtomicRmwXor32u(mem), + + I32_ATOMIC_RMW_XCHG => I32AtomicRmwXchg(mem), + I64_ATOMIC_RMW_XCHG => I64AtomicRmwXchg(mem), + I32_ATOMIC_RMW_XCHG8U => I32AtomicRmwXchg8u(mem), + I32_ATOMIC_RMW_XCHG16U => I32AtomicRmwXchg16u(mem), + I64_ATOMIC_RMW_XCHG8U => I64AtomicRmwXchg8u(mem), + I64_ATOMIC_RMW_XCHG16U => I64AtomicRmwXchg16u(mem), + I64_ATOMIC_RMW_XCHG32U => I64AtomicRmwXchg32u(mem), + + I32_ATOMIC_RMW_CMPXCHG => I32AtomicRmwCmpxchg(mem), + I64_ATOMIC_RMW_CMPXCHG => I64AtomicRmwCmpxchg(mem), + I32_ATOMIC_RMW_CMPXCHG8U => I32AtomicRmwCmpxchg8u(mem), + I32_ATOMIC_RMW_CMPXCHG16U => I32AtomicRmwCmpxchg16u(mem), + I64_ATOMIC_RMW_CMPXCHG8U => I64AtomicRmwCmpxchg8u(mem), + I64_ATOMIC_RMW_CMPXCHG16U => I64AtomicRmwCmpxchg16u(mem), + I64_ATOMIC_RMW_CMPXCHG32U => I64AtomicRmwCmpxchg32u(mem), + + _ => return Err(Error::UnknownOpcode(val)), + }) +} + +impl Deserialize for MemArg { + type Error = Error; + + fn deserialize(reader: &mut R) -> Result { + let align = Uint8::deserialize(reader)?; + let offset = VarUint32::deserialize(reader)?; + Ok(MemArg { align: align.into(), offset: offset.into() }) + } +} macro_rules! op { ($writer: expr, $byte: expr) => ({ @@ -804,6 +1051,13 @@ macro_rules! op { }); } +macro_rules! atomic { + ($writer: expr, $byte: expr, $mem:expr) => ({ + $writer.write(&[ATOMIC_PREFIX, $byte])?; + MemArg::serialize($mem, $writer)?; + }); +} + impl Serialize for Instruction { type Error = Error; @@ -1104,12 +1358,97 @@ impl Serialize for Instruction { I64ReinterpretF64 => op!(writer, I64REINTERPRETF64), F32ReinterpretI32 => op!(writer, F32REINTERPRETI32), F64ReinterpretI64 => op!(writer, F64REINTERPRETI64), + + AtomicWake(m) => atomic!(writer, ATOMIC_WAKE, m), + I32AtomicWait(m) => atomic!(writer, I32_ATOMIC_WAIT, m), + I64AtomicWait(m) => atomic!(writer, I64_ATOMIC_WAIT, m), + + I32AtomicLoad(m) => atomic!(writer, I32_ATOMIC_LOAD, m), + I64AtomicLoad(m) => atomic!(writer, I64_ATOMIC_LOAD, m), + I32AtomicLoad8u(m) => atomic!(writer, I32_ATOMIC_LOAD8U, m), + I32AtomicLoad16u(m) => atomic!(writer, I32_ATOMIC_LOAD16U, m), + I64AtomicLoad8u(m) => atomic!(writer, I64_ATOMIC_LOAD8U, m), + I64AtomicLoad16u(m) => atomic!(writer, I64_ATOMIC_LOAD16U, m), + I64AtomicLoad32u(m) => atomic!(writer, I64_ATOMIC_LOAD32U, m), + I32AtomicStore(m) => atomic!(writer, I32_ATOMIC_STORE, m), + I64AtomicStore(m) => atomic!(writer, I64_ATOMIC_STORE, m), + I32AtomicStore8u(m) => atomic!(writer, I32_ATOMIC_STORE8U, m), + I32AtomicStore16u(m) => atomic!(writer, I32_ATOMIC_STORE16U, m), + I64AtomicStore8u(m) => atomic!(writer, I64_ATOMIC_STORE8U, m), + I64AtomicStore16u(m) => atomic!(writer, I64_ATOMIC_STORE16U, m), + I64AtomicStore32u(m) => atomic!(writer, I64_ATOMIC_STORE32U, m), + + I32AtomicRmwAdd(m) => atomic!(writer, I32_ATOMIC_RMW_ADD, m), + I64AtomicRmwAdd(m) => atomic!(writer, I64_ATOMIC_RMW_ADD, m), + I32AtomicRmwAdd8u(m) => atomic!(writer, I32_ATOMIC_RMW_ADD8U, m), + I32AtomicRmwAdd16u(m) => atomic!(writer, I32_ATOMIC_RMW_ADD16U, m), + I64AtomicRmwAdd8u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD8U, m), + I64AtomicRmwAdd16u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD16U, m), + I64AtomicRmwAdd32u(m) => atomic!(writer, I64_ATOMIC_RMW_ADD32U, m), + + I32AtomicRmwSub(m) => atomic!(writer, I32_ATOMIC_RMW_SUB, m), + I64AtomicRmwSub(m) => atomic!(writer, I64_ATOMIC_RMW_SUB, m), + I32AtomicRmwSub8u(m) => atomic!(writer, I32_ATOMIC_RMW_SUB8U, m), + I32AtomicRmwSub16u(m) => atomic!(writer, I32_ATOMIC_RMW_SUB16U, m), + I64AtomicRmwSub8u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB8U, m), + I64AtomicRmwSub16u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB16U, m), + I64AtomicRmwSub32u(m) => atomic!(writer, I64_ATOMIC_RMW_SUB32U, m), + + I32AtomicRmwAnd(m) => atomic!(writer, I32_ATOMIC_RMW_AND, m), + I64AtomicRmwAnd(m) => atomic!(writer, I64_ATOMIC_RMW_AND, m), + I32AtomicRmwAnd8u(m) => atomic!(writer, I32_ATOMIC_RMW_AND8U, m), + I32AtomicRmwAnd16u(m) => atomic!(writer, I32_ATOMIC_RMW_AND16U, m), + I64AtomicRmwAnd8u(m) => atomic!(writer, I64_ATOMIC_RMW_AND8U, m), + I64AtomicRmwAnd16u(m) => atomic!(writer, I64_ATOMIC_RMW_AND16U, m), + I64AtomicRmwAnd32u(m) => atomic!(writer, I64_ATOMIC_RMW_AND32U, m), + + I32AtomicRmwOr(m) => atomic!(writer, I32_ATOMIC_RMW_OR, m), + I64AtomicRmwOr(m) => atomic!(writer, I64_ATOMIC_RMW_OR, m), + I32AtomicRmwOr8u(m) => atomic!(writer, I32_ATOMIC_RMW_OR8U, m), + I32AtomicRmwOr16u(m) => atomic!(writer, I32_ATOMIC_RMW_OR16U, m), + I64AtomicRmwOr8u(m) => atomic!(writer, I64_ATOMIC_RMW_OR8U, m), + I64AtomicRmwOr16u(m) => atomic!(writer, I64_ATOMIC_RMW_OR16U, m), + I64AtomicRmwOr32u(m) => atomic!(writer, I64_ATOMIC_RMW_OR32U, m), + + I32AtomicRmwXor(m) => atomic!(writer, I32_ATOMIC_RMW_XOR, m), + I64AtomicRmwXor(m) => atomic!(writer, I64_ATOMIC_RMW_XOR, m), + I32AtomicRmwXor8u(m) => atomic!(writer, I32_ATOMIC_RMW_XOR8U, m), + I32AtomicRmwXor16u(m) => atomic!(writer, I32_ATOMIC_RMW_XOR16U, m), + I64AtomicRmwXor8u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR8U, m), + I64AtomicRmwXor16u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR16U, m), + I64AtomicRmwXor32u(m) => atomic!(writer, I64_ATOMIC_RMW_XOR32U, m), + + I32AtomicRmwXchg(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG, m), + I64AtomicRmwXchg(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG, m), + I32AtomicRmwXchg8u(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG8U, m), + I32AtomicRmwXchg16u(m) => atomic!(writer, I32_ATOMIC_RMW_XCHG16U, m), + I64AtomicRmwXchg8u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG8U, m), + I64AtomicRmwXchg16u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG16U, m), + I64AtomicRmwXchg32u(m) => atomic!(writer, I64_ATOMIC_RMW_XCHG32U, m), + + I32AtomicRmwCmpxchg(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG, m), + I64AtomicRmwCmpxchg(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG, m), + I32AtomicRmwCmpxchg8u(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG8U, m), + I32AtomicRmwCmpxchg16u(m) => atomic!(writer, I32_ATOMIC_RMW_CMPXCHG16U, m), + I64AtomicRmwCmpxchg8u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG8U, m), + I64AtomicRmwCmpxchg16u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG16U, m), + I64AtomicRmwCmpxchg32u(m) => atomic!(writer, I64_ATOMIC_RMW_CMPXCHG32U, m), } Ok(()) } } +impl Serialize for MemArg { + type Error = Error; + + fn serialize(self, writer: &mut W) -> Result<(), Self::Error> { + Uint8::from(self.align).serialize(writer)?; + VarUint32::from(self.offset).serialize(writer)?; + Ok(()) + } +} + macro_rules! fmt_op { ($f: expr, $mnemonic: expr) => ({ write!($f, "{}", $mnemonic) @@ -1365,6 +1704,81 @@ impl fmt::Display for Instruction { I64ReinterpretF64 => write!(f, "i64.reinterpret/f64"), F32ReinterpretI32 => write!(f, "f32.reinterpret/i32"), F64ReinterpretI64 => write!(f, "f64.reinterpret/i64"), + + AtomicWake(_) => write!(f, "atomic.wake"), + I32AtomicWait(_) => write!(f, "i32.atomic.wait"), + I64AtomicWait(_) => write!(f, "i64.atomic.wait"), + + I32AtomicLoad(_) => write!(f, "i32.atomic.load"), + I64AtomicLoad(_) => write!(f, "i64.atomic.load"), + I32AtomicLoad8u(_) => write!(f, "i32.atomic.load8_u"), + I32AtomicLoad16u(_) => write!(f, "i32.atomic.load16_u"), + I64AtomicLoad8u(_) => write!(f, "i64.atomic.load8_u"), + I64AtomicLoad16u(_) => write!(f, "i64.atomic.load16_u"), + I64AtomicLoad32u(_) => write!(f, "i64.atomic.load32_u"), + I32AtomicStore(_) => write!(f, "i32.atomic.store"), + I64AtomicStore(_) => write!(f, "i64.atomic.store"), + I32AtomicStore8u(_) => write!(f, "i32.atomic.store8_u"), + I32AtomicStore16u(_) => write!(f, "i32.atomic.store16_u"), + I64AtomicStore8u(_) => write!(f, "i64.atomic.store8_u"), + I64AtomicStore16u(_) => write!(f, "i64.atomic.store16_u"), + I64AtomicStore32u(_) => write!(f, "i64.atomic.store32_u"), + + I32AtomicRmwAdd(_) => write!(f, "i32.atomic.rmw.add"), + I64AtomicRmwAdd(_) => write!(f, "i64.atomic.rmw.add"), + I32AtomicRmwAdd8u(_) => write!(f, "i32.atomic.rmw8_u.add"), + I32AtomicRmwAdd16u(_) => write!(f, "i32.atomic.rmw16_u.add"), + I64AtomicRmwAdd8u(_) => write!(f, "i64.atomic.rmw8_u.add"), + I64AtomicRmwAdd16u(_) => write!(f, "i64.atomic.rmw16_u.add"), + I64AtomicRmwAdd32u(_) => write!(f, "i64.atomic.rmw32_u.add"), + + I32AtomicRmwSub(_) => write!(f, "i32.atomic.rmw.sub"), + I64AtomicRmwSub(_) => write!(f, "i64.atomic.rmw.sub"), + I32AtomicRmwSub8u(_) => write!(f, "i32.atomic.rmw8_u.sub"), + I32AtomicRmwSub16u(_) => write!(f, "i32.atomic.rmw16_u.sub"), + I64AtomicRmwSub8u(_) => write!(f, "i64.atomic.rmw8_u.sub"), + I64AtomicRmwSub16u(_) => write!(f, "i64.atomic.rmw16_u.sub"), + I64AtomicRmwSub32u(_) => write!(f, "i64.atomic.rmw32_u.sub"), + + I32AtomicRmwAnd(_) => write!(f, "i32.atomic.rmw.and"), + I64AtomicRmwAnd(_) => write!(f, "i64.atomic.rmw.and"), + I32AtomicRmwAnd8u(_) => write!(f, "i32.atomic.rmw8_u.and"), + I32AtomicRmwAnd16u(_) => write!(f, "i32.atomic.rmw16_u.and"), + I64AtomicRmwAnd8u(_) => write!(f, "i64.atomic.rmw8_u.and"), + I64AtomicRmwAnd16u(_) => write!(f, "i64.atomic.rmw16_u.and"), + I64AtomicRmwAnd32u(_) => write!(f, "i64.atomic.rmw32_u.and"), + + I32AtomicRmwOr(_) => write!(f, "i32.atomic.rmw.or"), + I64AtomicRmwOr(_) => write!(f, "i64.atomic.rmw.or"), + I32AtomicRmwOr8u(_) => write!(f, "i32.atomic.rmw8_u.or"), + I32AtomicRmwOr16u(_) => write!(f, "i32.atomic.rmw16_u.or"), + I64AtomicRmwOr8u(_) => write!(f, "i64.atomic.rmw8_u.or"), + I64AtomicRmwOr16u(_) => write!(f, "i64.atomic.rmw16_u.or"), + I64AtomicRmwOr32u(_) => write!(f, "i64.atomic.rmw32_u.or"), + + I32AtomicRmwXor(_) => write!(f, "i32.atomic.rmw.xor"), + I64AtomicRmwXor(_) => write!(f, "i64.atomic.rmw.xor"), + I32AtomicRmwXor8u(_) => write!(f, "i32.atomic.rmw8_u.xor"), + I32AtomicRmwXor16u(_) => write!(f, "i32.atomic.rmw16_u.xor"), + I64AtomicRmwXor8u(_) => write!(f, "i64.atomic.rmw8_u.xor"), + I64AtomicRmwXor16u(_) => write!(f, "i64.atomic.rmw16_u.xor"), + I64AtomicRmwXor32u(_) => write!(f, "i64.atomic.rmw32_u.xor"), + + I32AtomicRmwXchg(_) => write!(f, "i32.atomic.rmw.xchg"), + I64AtomicRmwXchg(_) => write!(f, "i64.atomic.rmw.xchg"), + I32AtomicRmwXchg8u(_) => write!(f, "i32.atomic.rmw8_u.xchg"), + I32AtomicRmwXchg16u(_) => write!(f, "i32.atomic.rmw16_u.xchg"), + I64AtomicRmwXchg8u(_) => write!(f, "i64.atomic.rmw8_u.xchg"), + I64AtomicRmwXchg16u(_) => write!(f, "i64.atomic.rmw16_u.xchg"), + I64AtomicRmwXchg32u(_) => write!(f, "i64.atomic.rmw32_u.xchg"), + + I32AtomicRmwCmpxchg(_) => write!(f, "i32.atomic.rmw.cmpxchg"), + I64AtomicRmwCmpxchg(_) => write!(f, "i64.atomic.rmw.cmpxchg"), + I32AtomicRmwCmpxchg8u(_) => write!(f, "i32.atomic.rmw8_u.cmpxchg"), + I32AtomicRmwCmpxchg16u(_) => write!(f, "i32.atomic.rmw16_u.cmpxchg"), + I64AtomicRmwCmpxchg8u(_) => write!(f, "i64.atomic.rmw8_u.cmpxchg"), + I64AtomicRmwCmpxchg16u(_) => write!(f, "i64.atomic.rmw16_u.cmpxchg"), + I64AtomicRmwCmpxchg32u(_) => write!(f, "i64.atomic.rmw32_u.cmpxchg"), } } }