@@ -877,6 +877,37 @@ void WasmBinaryWriter::visitAtomicRMW(AtomicRMW *curr) {
877877 emitMemoryAccess (curr->bytes , curr->bytes , curr->offset );
878878}
879879
880+ void WasmBinaryWriter::visitAtomicCmpxchg (AtomicCmpxchg *curr) {
881+ if (debug) std::cerr << " zz node: AtomicCmpxchg" << std::endl;
882+ recurse (curr->ptr );
883+ recurse (curr->expected );
884+ recurse (curr->replacement );
885+
886+ o << int8_t (BinaryConsts::AtomicPrefix);
887+ switch (curr->type ) {
888+ case i32 :
889+ switch (curr->bytes ) {
890+ case 1 : o << int8_t (BinaryConsts::I32AtomicCmpxchg8U); break ;
891+ case 2 : o << int8_t (BinaryConsts::I32AtomicCmpxchg16U); break ;
892+ case 4 : o << int8_t (BinaryConsts::I32AtomicCmpxchg); break ;
893+ default : WASM_UNREACHABLE ();
894+ }
895+ break ;
896+ case i64 :
897+ switch (curr->bytes ) {
898+ case 1 : o << int8_t (BinaryConsts::I64AtomicCmpxchg8U); break ;
899+ case 2 : o << int8_t (BinaryConsts::I64AtomicCmpxchg16U); break ;
900+ case 4 : o << int8_t (BinaryConsts::I64AtomicCmpxchg32U); break ;
901+ case 8 : o << int8_t (BinaryConsts::I64AtomicCmpxchg); break ;
902+ default : WASM_UNREACHABLE ();
903+ }
904+ break ;
905+ default : WASM_UNREACHABLE ();
906+ }
907+ emitMemoryAccess (curr->bytes , curr->bytes , curr->offset );
908+ }
909+
910+
880911void WasmBinaryWriter::visitConst (Const *curr) {
881912 if (debug) std::cerr << " zz node: Const" << curr << " : " << curr->type << std::endl;
882913 switch (curr->type ) {
@@ -1980,6 +2011,7 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
19802011 if (maybeVisitLoad (curr, code, /* isAtomic=*/ true )) break ;
19812012 if (maybeVisitStore (curr, code, /* isAtomic=*/ true )) break ;
19822013 if (maybeVisitAtomicRMW (curr, code)) break ;
2014+ if (maybeVisitAtomicCmpxchg (curr, code)) break ;
19832015 throw ParseException (" invalid code after atomic prefix: " + std::to_string (code));
19842016 }
19852017 default : {
@@ -2372,6 +2404,38 @@ bool WasmBinaryBuilder::maybeVisitAtomicRMW(Expression*& out, uint8_t code) {
23722404 return true ;
23732405}
23742406
2407+ bool WasmBinaryBuilder::maybeVisitAtomicCmpxchg (Expression*& out, uint8_t code) {
2408+ if (code < BinaryConsts::AtomicCmpxchgOps_Begin || code > BinaryConsts::AtomicCmpxchgOps_End) return false ;
2409+ auto * curr = allocator.alloc <AtomicCmpxchg>();
2410+
2411+ // Set curr to the given type and size.
2412+ #define SET (optype, size ) \
2413+ curr->type = optype; \
2414+ curr->bytes = size
2415+
2416+ switch (code) {
2417+ case BinaryConsts::I32AtomicCmpxchg: SET (i32 , 4 ); break ;
2418+ case BinaryConsts::I64AtomicCmpxchg: SET (i64 , 8 ); break ;
2419+ case BinaryConsts::I32AtomicCmpxchg8U: SET (i32 , 1 ); break ;
2420+ case BinaryConsts::I32AtomicCmpxchg16U: SET (i32 , 2 ); break ;
2421+ case BinaryConsts::I64AtomicCmpxchg8U: SET (i64 , 1 ); break ;
2422+ case BinaryConsts::I64AtomicCmpxchg16U: SET (i64 , 2 ); break ;
2423+ case BinaryConsts::I64AtomicCmpxchg32U: SET (i64 , 4 ); break ;
2424+ default : WASM_UNREACHABLE ();
2425+ }
2426+
2427+ if (debug) std::cerr << " zz node: AtomicCmpxchg" << std::endl;
2428+ Address readAlign;
2429+ readMemoryAccess (readAlign, curr->bytes , curr->offset );
2430+ if (readAlign != curr->bytes ) throw ParseException (" Align of AtomicCpxchg must match size" );
2431+ curr->replacement = popNonVoidExpression ();
2432+ curr->expected = popNonVoidExpression ();
2433+ curr->ptr = popNonVoidExpression ();
2434+ curr->finalize ();
2435+ out = curr;
2436+ return true ;
2437+ }
2438+
23752439bool WasmBinaryBuilder::maybeVisitConst (Expression*& out, uint8_t code) {
23762440 Const* curr;
23772441 if (debug) std::cerr << " zz node: Const, code " << code << std::endl;
0 commit comments