summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r--src/wasm/wasm-binary.cpp64
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;