Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1382,15 +1382,15 @@ BinaryenExpressionRef BinaryenAtomicRMW(BinaryenModuleRef module,
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,
Expand Down
7 changes: 5 additions & 2 deletions src/ir/properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,8 +507,11 @@ inline MemoryOrder getMemoryOrder(Expression* curr) {
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;
Expand Down
10 changes: 6 additions & 4 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,8 @@ struct NullInstrParserCtx {
Type,
int,
MemoryIdxT*,
MemargT) {
MemargT,
MemoryOrder) {
return Ok{};
}
Result<> makeAtomicCmpxchg(
Expand Down Expand Up @@ -2274,11 +2275,12 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
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,
Expand Down
2 changes: 1 addition & 1 deletion src/parser/parsers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1818,7 +1818,7 @@ Result<> makeAtomicRMW(Ctx& ctx,
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>
Expand Down
3 changes: 2 additions & 1 deletion src/tools/fuzzing/fuzzing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4770,7 +4770,8 @@ Expression* TranslateToFuzzReader::makeAtomic(Type type) {
ptr,
value,
type,
wasm.memories[0]->name);
wasm.memories[0]->name,
MemoryOrder::SeqCst);
} else {
auto* expected = make(type);
auto* replacement = make(type);
Expand Down
6 changes: 4 additions & 2 deletions src/wasm-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,16 +466,18 @@ class Builder {
Expression* ptr,
Expression* value,
Type type,
Name memory) {
Name memory,
MemoryOrder order) {
auto* ret = wasm.allocator.alloc<AtomicRMW>();
ret->op = op;
ret->bytes = bytes;
ret->offset = offset;
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,
Expand Down
1 change: 1 addition & 0 deletions src/wasm-delegations-fields.def
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ DELEGATE_FIELD_CHILD(AtomicRMW, ptr)
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)

Expand Down
8 changes: 6 additions & 2 deletions src/wasm-ir-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,8 +160,12 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
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);
Expand Down
1 change: 1 addition & 0 deletions src/wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,7 @@ class AtomicRMW : public SpecificExpression<Expression::AtomicRMWId> {
Expression* ptr;
Expression* value;
Name memory;
MemoryOrder order = MemoryOrder::SeqCst;

void finalize();
};
Expand Down
21 changes: 14 additions & 7 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3704,31 +3704,38 @@ Result<> WasmBinaryReader::readInst() {
#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);
Expand Down
14 changes: 9 additions & 5 deletions src/wasm/wasm-ir-builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1075,7 +1075,7 @@ Result<> IRBuilder::visitEnd() {
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);
Expand Down Expand Up @@ -1503,14 +1503,18 @@ Result<> IRBuilder::makeAtomicStore(
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{};
}

Expand Down
50 changes: 40 additions & 10 deletions src/wasm/wasm-validator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1108,11 +1108,17 @@ void FunctionValidator::visitLoad(Load* curr) {
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(),
Expand Down Expand Up @@ -1147,11 +1153,17 @@ void FunctionValidator::visitStore(Store* curr) {
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(),
Expand Down Expand Up @@ -1185,6 +1197,24 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
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,
Expand Down
Loading