diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index b93eaa103e7..146a9089f1f 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -2698,12 +2698,13 @@ void BinaryenLoadSetPtr(BinaryenExpressionRef expr, bool BinaryenStoreIsAtomic(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); - return static_cast(expression)->isAtomic; + return static_cast(expression)->isAtomic(); } void BinaryenStoreSetAtomic(BinaryenExpressionRef expr, bool isAtomic) { auto* expression = (Expression*)expr; assert(expression->is()); - static_cast(expression)->isAtomic = isAtomic != 0; + static_cast(expression)->order = + isAtomic ? MemoryOrder::SeqCst : MemoryOrder::Unordered; } uint32_t BinaryenStoreGetBytes(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; diff --git a/src/ir/cost.h b/src/ir/cost.h index 0c27e694e5c..41477af6e62 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -105,7 +105,7 @@ struct CostAnalyzer : public OverriddenVisitor { } CostType visitStore(Store* curr) { return 2 + visit(curr->ptr) + visit(curr->value) + - AtomicCost * curr->isAtomic; + AtomicCost * curr->isAtomic(); } CostType visitAtomicRMW(AtomicRMW* curr) { return AtomicCost + visit(curr->ptr) + visit(curr->value); diff --git a/src/ir/effects.h b/src/ir/effects.h index 1fce1b3ebc5..b9e07a87bf8 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -603,7 +603,7 @@ class EffectAnalyzer { } void visitStore(Store* curr) { parent.writesMemory = true; - parent.isAtomic |= curr->isAtomic; + parent.isAtomic |= curr->isAtomic(); parent.implicitTrap = true; } void visitAtomicRMW(AtomicRMW* curr) { diff --git a/src/ir/properties.h b/src/ir/properties.h index f65e2375eff..e1865bea562 100644 --- a/src/ir/properties.h +++ b/src/ir/properties.h @@ -505,7 +505,7 @@ inline MemoryOrder getMemoryOrder(Expression* curr) { return load->order; } if (auto* store = curr->dynCast()) { - return store->isAtomic ? MemoryOrder::SeqCst : MemoryOrder::Unordered; + return store->order; } if (curr->is() || curr->is() || curr->is() || curr->is()) { diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp index 96d4cd5b9bb..d127ebdc8e2 100644 --- a/src/passes/I64ToI32Lowering.cpp +++ b/src/passes/I64ToI32Lowering.cpp @@ -458,7 +458,7 @@ struct I64ToI32Lowering : public WalkerPass> { return; } assert(curr->offset + 4 > curr->offset); - assert(!curr->isAtomic && "atomic store not implemented"); + assert(!curr->isAtomic() && "atomic store not implemented"); TempVar highBits = fetchOutParam(curr->value); uint8_t bytes = curr->bytes; curr->bytes = std::min(curr->bytes, uint8_t(4)); diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 9ef6ccd4716..ad5c0925e6a 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1282,7 +1282,7 @@ struct OptimizeInstructions // instead of wrapping to 32, just store some of the bits in the i64 curr->valueType = Type::i64; curr->value = unary->value; - } else if (!curr->isAtomic && Abstract::hasAnyReinterpret(unary->op) && + } else if (!curr->isAtomic() && Abstract::hasAnyReinterpret(unary->op) && curr->bytes == curr->valueType.getByteSize()) { // f32.store(y, f32.reinterpret_i32(x)) => i32.store(y, x) // f64.store(y, f64.reinterpret_i64(x)) => i64.store(y, x) diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index c83cccbe5dd..d2c76c67208 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -583,7 +583,7 @@ struct PrintExpressionContents } void visitStore(Store* curr) { prepareColor(o) << forceConcrete(curr->valueType); - if (curr->isAtomic) { + if (curr->isAtomic()) { o << ".atomic"; } o << ".store"; diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index 12e516f66f5..124f8a383bc 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -55,7 +55,7 @@ static Name getStoreName(Store* curr) { std::string ret = "SAFE_HEAP_STORE_"; ret += curr->valueType.toString(); ret += "_" + std::to_string(curr->bytes) + "_"; - if (curr->isAtomic) { + if (curr->isAtomic()) { ret += "A"; } else { ret += std::to_string(curr->align); @@ -270,7 +270,8 @@ struct SafeHeap : public Pass { continue; } for (auto isAtomic : {true, false}) { - store.isAtomic = isAtomic; + store.order = + isAtomic ? MemoryOrder::SeqCst : MemoryOrder::Unordered; if (isAtomic && !isPossibleAtomicOperation( align, bytes, module->memories[0]->shared, valueType)) { diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index ef863fe016d..22e48ef4ac3 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -3358,7 +3358,7 @@ Expression* TranslateToFuzzReader::makeStore(Type type) { } // make it atomic wasm.memories[0]->shared = true; - store->isAtomic = true; + store->order = MemoryOrder::SeqCst; store->align = store->bytes; return store; } diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 4cdeeb0bffd..fb273b32568 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -428,7 +428,6 @@ class Builder { Type type, Name memory) { auto* ret = wasm.allocator.alloc(); - ret->isAtomic = false; ret->bytes = bytes; ret->offset = offset; ret->align = align; @@ -436,6 +435,7 @@ class Builder { ret->value = value; ret->valueType = type; ret->memory = memory; + ret->order = MemoryOrder::Unordered; ret->finalize(); return ret; } @@ -446,7 +446,7 @@ class Builder { Type type, Name memory) { Store* store = makeStore(bytes, offset, bytes, ptr, value, type, memory); - store->isAtomic = true; + store->order = MemoryOrder::SeqCst; return store; } AtomicRMW* makeAtomicRMW(AtomicRMWOp op, diff --git a/src/wasm-delegations-fields.def b/src/wasm-delegations-fields.def index c5df66a3439..8cb5df64838 100644 --- a/src/wasm-delegations-fields.def +++ b/src/wasm-delegations-fields.def @@ -364,7 +364,7 @@ DELEGATE_FIELD_CHILD(Store, ptr) DELEGATE_FIELD_INT(Store, bytes) DELEGATE_FIELD_ADDRESS(Store, offset) DELEGATE_FIELD_ADDRESS(Store, align) -DELEGATE_FIELD_INT(Store, isAtomic) +DELEGATE_FIELD_INT(Store, order) DELEGATE_FIELD_TYPE(Store, valueType) DELEGATE_FIELD_NAME_KIND(Store, memory, ModuleItemKind::Memory) DELEGATE_FIELD_CASE_END(Store) diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 1ea0aeb5e66..86895d374d2 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -3966,7 +3966,7 @@ class ModuleRunnerBase : public ExpressionRunner { auto memorySize = info.instance->getMemorySize(info.name); auto addr = info.instance->getFinalAddress(curr, ptr.getSingleValue(), memorySize); - if (curr->isAtomic) { + if (curr->isAtomic()) { info.instance->checkAtomicAddress(addr, curr->bytes, memorySize); } info.interface()->store(curr, addr, value.getSingleValue(), info.name); @@ -5136,7 +5136,7 @@ class ModuleRunnerBase : public ExpressionRunner { Store store; store.bytes = bytes; store.align = bytes; - store.isAtomic = true; // understatement + store.order = MemoryOrder::SeqCst; store.ptr = &ptr; store.value = &value; store.valueType = value.type; diff --git a/src/wasm.h b/src/wasm.h index 3e08a99e3d2..f5ba53ea934 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1012,11 +1012,13 @@ class Store : public SpecificExpression { uint8_t bytes; Address offset; Address align; - bool isAtomic; Expression* ptr; Expression* value; Type valueType; Name memory; + MemoryOrder order; + + bool isAtomic() const { return order != MemoryOrder::Unordered; } void finalize(); }; diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1ec8ba7e619..45a97fab3b7 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -365,7 +365,7 @@ void BinaryInstWriter::visitLoad(Load* curr) { } void BinaryInstWriter::visitStore(Store* curr) { - if (!curr->isAtomic) { + if (!curr->isAtomic()) { switch (curr->valueType.getBasic()) { case Type::i32: { switch (curr->bytes) { diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 59f755a19ef..3159d99ca5b 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1128,7 +1128,7 @@ void FunctionValidator::visitLoad(Load* curr) { void FunctionValidator::visitStore(Store* curr) { auto* memory = getModule()->getMemoryOrNull(curr->memory); shouldBeTrue(!!memory, curr, "memory.store memory must exist"); - if (curr->isAtomic) { + if (curr->isAtomic()) { shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operations require threads [--enable-threads]"); @@ -1145,7 +1145,7 @@ void FunctionValidator::visitStore(Store* curr) { validateMemBytes(curr->bytes, curr->valueType, curr); validateOffset(curr->offset, memory, curr); validateAlignment( - curr->align, curr->valueType, curr->bytes, curr->isAtomic, curr); + curr->align, curr->valueType, curr->bytes, curr->isAtomic(), curr); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, memory->addressType, @@ -1157,7 +1157,7 @@ void FunctionValidator::visitStore(Store* curr) { "store value type must not be none"); shouldBeEqualOrFirstIsUnreachable( curr->value->type, curr->valueType, curr, "store value type must match"); - if (curr->isAtomic) { + if (curr->isAtomic()) { shouldBeIntOrUnreachable( curr->valueType, curr, "atomic stores must be of integers"); } diff --git a/src/wasm2js.h b/src/wasm2js.h index 5725b3b0d76..f298a3d0ebc 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -1562,7 +1562,7 @@ Ref Wasm2JSBuilder::processExpression(Expression* curr, Fatal() << "Unhandled type in store: " << curr->valueType; } } - if (curr->isAtomic) { + if (curr->isAtomic()) { Ref call = ValueBuilder::makeCall( ValueBuilder::makeDot(ValueBuilder::makeName(ATOMICS), STORE)); ValueBuilder::appendToCall(call, ret[1]);