diff options
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 69d3ecdbb..efbd82e8b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -877,6 +877,37 @@ void WasmBinaryWriter::visitAtomicRMW(AtomicRMW *curr) { emitMemoryAccess(curr->bytes, curr->bytes, curr->offset); } +void WasmBinaryWriter::visitAtomicCmpxchg(AtomicCmpxchg *curr) { + if (debug) std::cerr << "zz node: AtomicCmpxchg" << std::endl; + recurse(curr->ptr); + recurse(curr->expected); + recurse(curr->replacement); + + o << int8_t(BinaryConsts::AtomicPrefix); + switch (curr->type) { + case i32: + switch (curr->bytes) { + case 1: o << int8_t(BinaryConsts::I32AtomicCmpxchg8U); break; + case 2: o << int8_t(BinaryConsts::I32AtomicCmpxchg16U); break; + case 4: o << int8_t(BinaryConsts::I32AtomicCmpxchg); break; + default: WASM_UNREACHABLE(); + } + break; + case i64: + switch (curr->bytes) { + case 1: o << int8_t(BinaryConsts::I64AtomicCmpxchg8U); break; + case 2: o << int8_t(BinaryConsts::I64AtomicCmpxchg16U); break; + case 4: o << int8_t(BinaryConsts::I64AtomicCmpxchg32U); break; + case 8: o << int8_t(BinaryConsts::I64AtomicCmpxchg); break; + default: WASM_UNREACHABLE(); + } + break; + default: WASM_UNREACHABLE(); + } + emitMemoryAccess(curr->bytes, curr->bytes, curr->offset); +} + + void WasmBinaryWriter::visitConst(Const *curr) { if (debug) std::cerr << "zz node: Const" << curr << " : " << curr->type << std::endl; switch (curr->type) { @@ -1980,6 +2011,7 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitLoad(curr, code, /*isAtomic=*/true)) break; if (maybeVisitStore(curr, code, /*isAtomic=*/true)) break; if (maybeVisitAtomicRMW(curr, code)) break; + if (maybeVisitAtomicCmpxchg(curr, code)) break; throw ParseException("invalid code after atomic prefix: " + std::to_string(code)); } default: { @@ -2372,6 +2404,38 @@ bool WasmBinaryBuilder::maybeVisitAtomicRMW(Expression*& out, uint8_t code) { return true; } +bool WasmBinaryBuilder::maybeVisitAtomicCmpxchg(Expression*& out, uint8_t code) { + if (code < BinaryConsts::AtomicCmpxchgOps_Begin || code > BinaryConsts::AtomicCmpxchgOps_End) return false; + auto* curr = allocator.alloc<AtomicCmpxchg>(); + + // Set curr to the given type and size. +#define SET(optype, size) \ + curr->type = optype; \ + curr->bytes = size + + switch (code) { + case BinaryConsts::I32AtomicCmpxchg: SET(i32, 4); break; + case BinaryConsts::I64AtomicCmpxchg: SET(i64, 8); break; + case BinaryConsts::I32AtomicCmpxchg8U: SET(i32, 1); break; + case BinaryConsts::I32AtomicCmpxchg16U: SET(i32, 2); break; + case BinaryConsts::I64AtomicCmpxchg8U: SET(i64, 1); break; + case BinaryConsts::I64AtomicCmpxchg16U: SET(i64, 2); break; + case BinaryConsts::I64AtomicCmpxchg32U: SET(i64, 4); break; + default: WASM_UNREACHABLE(); + } + + if (debug) std::cerr << "zz node: AtomicCmpxchg" << std::endl; + Address readAlign; + readMemoryAccess(readAlign, curr->bytes, curr->offset); + if (readAlign != curr->bytes) throw ParseException("Align of AtomicCpxchg must match size"); + curr->replacement = popNonVoidExpression(); + curr->expected = popNonVoidExpression(); + curr->ptr = popNonVoidExpression(); + curr->finalize(); + out = curr; + return true; +} + bool WasmBinaryBuilder::maybeVisitConst(Expression*& out, uint8_t code) { Const* curr; if (debug) std::cerr << "zz node: Const, code " << code << std::endl; |