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,