gemini: add ordering field for rmw
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index e38e60c..631500f 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp
@@ -1382,15 +1382,15 @@ BinaryenExpressionRef value, BinaryenType type, const char* memoryName) { - return static_cast<Expression*>( - Builder(*(Module*)module) - .makeAtomicRMW(AtomicRMWOp(op), - bytes, - offset, - (Expression*)ptr, - (Expression*)value, - Type(type), - getMemoryName(module, memoryName))); + return Builder(*(Module*)module) + .makeAtomicRMW(AtomicRMWOp(op), + bytes, + offset, + (Expression*)ptr, + (Expression*)value, + Type(type), + Name(memoryName), + MemoryOrder::SeqCst); } BinaryenExpressionRef BinaryenAtomicCmpxchg(BinaryenModuleRef module, BinaryenIndex bytes,
diff --git a/src/ir/properties.h b/src/ir/properties.h index e1865be..e28a519 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h
@@ -507,8 +507,11 @@ if (auto* store = curr->dynCast<Store>()) { return store->order; } - if (curr->is<AtomicRMW>() || curr->is<AtomicWait>() || - curr->is<AtomicNotify>() || curr->is<AtomicFence>()) { + if (auto* rmw = curr->dynCast<AtomicRMW>()) { + return rmw->order; + } + if (curr->is<AtomicWait>() || curr->is<AtomicNotify>() || + curr->is<AtomicFence>()) { return MemoryOrder::SeqCst; } return MemoryOrder::Unordered;
diff --git a/src/parser/contexts.h b/src/parser/contexts.h index 1ac3a7c..82083ca 100644 --- a/src/parser/contexts.h +++ b/src/parser/contexts.h
@@ -575,7 +575,8 @@ Type, int, MemoryIdxT*, - MemargT) { + MemargT, + MemoryOrder) { return Ok{}; } Result<> makeAtomicCmpxchg( @@ -2274,11 +2275,12 @@ Type type, int bytes, Name* mem, - Memarg memarg) { + Memarg memarg, + MemoryOrder order) { auto m = getMemory(pos, mem); CHECK_ERR(m); - return withLoc(pos, - irBuilder.makeAtomicRMW(op, bytes, memarg.offset, type, *m)); + return withLoc( + pos, irBuilder.makeAtomicRMW(op, bytes, memarg.offset, type, *m, order)); } Result<> makeAtomicCmpxchg(Index pos,
diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 7712264..d9ef5d4 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h
@@ -1818,7 +1818,7 @@ auto arg = memarg(ctx, bytes); CHECK_ERR(arg); return ctx.makeAtomicRMW( - pos, annotations, op, type, bytes, mem.getPtr(), *arg); + pos, annotations, op, type, bytes, mem.getPtr(), *arg, MemoryOrder::SeqCst); } template<typename Ctx>
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 22e48ef..1aeaf9c 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp
@@ -4770,7 +4770,8 @@ ptr, value, type, - wasm.memories[0]->name); + wasm.memories[0]->name, + MemoryOrder::SeqCst); } else { auto* expected = make(type); auto* replacement = make(type);
diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 104b838..0d09fa6 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h
@@ -466,7 +466,8 @@ Expression* ptr, Expression* value, Type type, - Name memory) { + Name memory, + MemoryOrder order) { auto* ret = wasm.allocator.alloc<AtomicRMW>(); ret->op = op; ret->bytes = bytes; @@ -474,8 +475,9 @@ ret->ptr = ptr; ret->value = value; ret->type = type; - ret->finalize(); ret->memory = memory; + ret->order = order; + ret->finalize(); return ret; } AtomicCmpxchg* makeAtomicCmpxchg(unsigned bytes,
diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index 8cb5df6..143528b 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def
@@ -375,6 +375,7 @@ DELEGATE_FIELD_INT(AtomicRMW, op) DELEGATE_FIELD_INT(AtomicRMW, bytes) DELEGATE_FIELD_ADDRESS(AtomicRMW, offset) +DELEGATE_FIELD_INT(AtomicRMW, order) DELEGATE_FIELD_NAME_KIND(AtomicRMW, memory, ModuleItemKind::Memory) DELEGATE_FIELD_CASE_END(AtomicRMW)
diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h index bbc21af..5f06ddd 100644 --- a/src/wasm-ir-builder.h +++ b/src/wasm-ir-builder.h
@@ -160,8 +160,12 @@ unsigned bytes, Address offset, Type type, Name mem, MemoryOrder order); Result<> makeAtomicStore( unsigned bytes, Address offset, Type type, Name mem, MemoryOrder order); - Result<> makeAtomicRMW( - AtomicRMWOp op, unsigned bytes, Address offset, Type type, Name mem); + Result<> makeAtomicRMW(AtomicRMWOp op, + unsigned bytes, + Address offset, + Type type, + Name mem, + MemoryOrder order); Result<> makeAtomicCmpxchg(unsigned bytes, Address offset, Type type, Name mem); Result<> makeAtomicWait(Type type, Address offset, Name mem);
diff --git a/src/wasm.h b/src/wasm.h index ab6323b..07f015c 100644 --- a/src/wasm.h +++ b/src/wasm.h
@@ -1035,6 +1035,7 @@ Expression* ptr; Expression* value; Name memory; + MemoryOrder order = MemoryOrder::SeqCst; void finalize(); };
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 96fd205..2c73040 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp
@@ -3704,31 +3704,38 @@ #define RMW(op) \ case BinaryConsts::I32AtomicRMW##op: { \ auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \ - return builder.makeAtomicRMW(RMW##op, 4, offset, Type::i32, mem); \ + return builder.makeAtomicRMW( \ + RMW##op, 4, offset, Type::i32, mem, MemoryOrder::SeqCst); \ } \ case BinaryConsts::I32AtomicRMW##op##8U: { \ auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \ - return builder.makeAtomicRMW(RMW##op, 1, offset, Type::i32, mem); \ + return builder.makeAtomicRMW( \ + RMW##op, 1, offset, Type::i32, mem, MemoryOrder::SeqCst); \ } \ case BinaryConsts::I32AtomicRMW##op##16U: { \ auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \ - return builder.makeAtomicRMW(RMW##op, 2, offset, Type::i32, mem); \ + return builder.makeAtomicRMW( \ + RMW##op, 2, offset, Type::i32, mem, MemoryOrder::SeqCst); \ } \ case BinaryConsts::I64AtomicRMW##op: { \ auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \ - return builder.makeAtomicRMW(RMW##op, 8, offset, Type::i64, mem); \ + return builder.makeAtomicRMW( \ + RMW##op, 8, offset, Type::i64, mem, MemoryOrder::SeqCst); \ } \ case BinaryConsts::I64AtomicRMW##op##8U: { \ auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \ - return builder.makeAtomicRMW(RMW##op, 1, offset, Type::i64, mem); \ + return builder.makeAtomicRMW( \ + RMW##op, 1, offset, Type::i64, mem, MemoryOrder::SeqCst); \ } \ case BinaryConsts::I64AtomicRMW##op##16U: { \ auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \ - return builder.makeAtomicRMW(RMW##op, 2, offset, Type::i64, mem); \ + return builder.makeAtomicRMW( \ + RMW##op, 2, offset, Type::i64, mem, MemoryOrder::SeqCst); \ } \ case BinaryConsts::I64AtomicRMW##op##32U: { \ auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \ - return builder.makeAtomicRMW(RMW##op, 4, offset, Type::i64, mem); \ + return builder.makeAtomicRMW( \ + RMW##op, 4, offset, Type::i64, mem, MemoryOrder::SeqCst); \ } RMW(Add);
diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp index 57a2469..0144c8d 100644 --- a/src/wasm/wasm-ir-builder.cpp +++ b/src/wasm/wasm-ir-builder.cpp
@@ -1075,7 +1075,7 @@ tryy->name = scope.label; tryy->finalize(tryy->type); push(maybeWrapForLabel(tryy)); - } else if (Try * tryy; + } else if (Try* tryy; (tryy = scope.getCatch()) || (tryy = scope.getCatchAll())) { auto index = scope.getIndex(); setCatchBody(tryy, *expr, index); @@ -1503,14 +1503,18 @@ return Ok{}; } -Result<> IRBuilder::makeAtomicRMW( - AtomicRMWOp op, unsigned bytes, Address offset, Type type, Name mem) { +Result<> IRBuilder::makeAtomicRMW(AtomicRMWOp op, + unsigned bytes, + Address offset, + Type type, + Name mem, + MemoryOrder order) { AtomicRMW curr; curr.memory = mem; curr.type = type; CHECK_ERR(visitAtomicRMW(&curr)); - push( - builder.makeAtomicRMW(op, bytes, offset, curr.ptr, curr.value, type, mem)); + push(builder.makeAtomicRMW( + op, bytes, offset, curr.ptr, curr.value, type, mem, order)); return Ok{}; }
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 4e79976..6cf82bb 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp
@@ -1108,11 +1108,17 @@ curr, "Atomic load should be i32 or i64"); } - if (curr->order == MemoryOrder::AcqRel) { - shouldBeTrue(getModule()->features.hasRelaxedAtomics(), - curr, - "Acquire/release operations require relaxed atomics " - "[--enable-relaxed-atomics]"); + switch (curr->order) { + case MemoryOrder::AcqRel: { + shouldBeTrue(getModule()->features.hasRelaxedAtomics(), + curr, + "Acquire/release operations require relaxed atomics " + "[--enable-relaxed-atomics]"); + break; + } + case MemoryOrder::Unordered: + case MemoryOrder::SeqCst: + break; } if (curr->type == Type::v128) { shouldBeTrue(getModule()->features.hasSIMD(), @@ -1147,11 +1153,17 @@ curr, "Atomic store should be i32 or i64"); } - if (curr->order == MemoryOrder::AcqRel) { - shouldBeTrue(getModule()->features.hasRelaxedAtomics(), - curr, - "Acquire/release operations require relaxed atomics " - "[--enable-relaxed-atomics]"); + switch (curr->order) { + case MemoryOrder::AcqRel: { + shouldBeTrue(getModule()->features.hasRelaxedAtomics(), + curr, + "Acquire/release operations require relaxed atomics " + "[--enable-relaxed-atomics]"); + break; + } + case MemoryOrder::Unordered: + case MemoryOrder::SeqCst: + break; } if (curr->valueType == Type::v128) { shouldBeTrue(getModule()->features.hasSIMD(), @@ -1185,6 +1197,24 @@ shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operations require threads [--enable-threads]"); + + switch (curr->order) { + case MemoryOrder::AcqRel: { + shouldBeTrue(getModule()->features.hasRelaxedAtomics(), + curr, + "Acquire/release operations require relaxed atomics " + "[--enable-relaxed-atomics]"); + break; + } + // Unordered RMW should be impossible unless there's a bug in the code. + case MemoryOrder::Unordered: { + WASM_UNREACHABLE("Atomic RMW can't be unordered"); + break; + } + case MemoryOrder::SeqCst: + break; + } + validateMemBytes(curr->bytes, curr->type, curr); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type,