diff --git a/CHANGELOG.md b/CHANGELOG.md index 11f61958d7f..624c51c7d98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,16 @@ full changeset diff at the end of each section. Current Trunk ------------- -- The c api now has separate functions for `CallRef` and `ReturnCallRef` matching the semantics of `Call` and `ReturnCall`. +- The C api now has separate functions for `CallRef` and `ReturnCallRef` matching the semantics of `Call` and `ReturnCall` (#8121). +- Breaking changes to the C and JS APIs related to atomic operations, in order +to support the relaxed atomics proposal (currently a part of the [shared everything threads proposal](https://github.com/WebAssembly/shared-everything-threads)) (#8248). + - `setAtomic` on atomic loads/stores is removed in favor of `setMemoryOrder` + `BinaryenLoadSetAtomic(expr, false)` / `load.setAtomic(false)` may be replaced with `BinaryenLoadSetMemoryOrder(expr, BinaryenMemoryOrderUnordered())`, + `BinaryenLoadSetAtomic(expr, true)` / `load.setAtomic(true)` may be replaced with `BinaryenLoadSetMemoryOrder(expr, BinaryenMemoryOrderSeqCst())`, + and likewise for `Store`s. In addition to Unordered and SeqCst, these functions support AcqRel which implements acquire/release semantics. + - Likewise `BinaryenAtomicLoad`, `BinaryenAtomicStore`, `BinaryenAtomicRMW`, and `BinaryenAtomicCmpxchg` + are updated with an additional `BinaryenMemoryOrder` param. The functions + formerly implicitly used `BinaryenMemoryOrderSeqCst()`. In JS this param is optional and thus not breaking. v125 ---- diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 825ea59326e..5186f9a3702 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -419,6 +419,18 @@ BinaryenExternalKind BinaryenExternalTag(void) { return static_cast(ExternalKind::Tag); } +// MemoryOrder for atomic operations + +BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderUnordered(void) { + return static_cast(MemoryOrder::Unordered); +} +BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderAcqRel(void) { + return static_cast(MemoryOrder::AcqRel); +} +BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderSeqCst(void) { + return static_cast(MemoryOrder::SeqCst); +} + // Features BinaryenFeatures BinaryenFeatureMVP(void) { @@ -1347,7 +1359,8 @@ BinaryenExpressionRef BinaryenAtomicLoad(BinaryenModuleRef module, uint32_t offset, BinaryenType type, BinaryenExpressionRef ptr, - const char* memoryName) { + const char* memoryName, + BinaryenMemoryOrder order) { return static_cast( Builder(*(Module*)module) .makeAtomicLoad(bytes, @@ -1355,7 +1368,7 @@ BinaryenExpressionRef BinaryenAtomicLoad(BinaryenModuleRef module, (Expression*)ptr, Type(type), getMemoryName(module, memoryName), - MemoryOrder::SeqCst)); + static_cast(order))); } BinaryenExpressionRef BinaryenAtomicStore(BinaryenModuleRef module, uint32_t bytes, @@ -1363,7 +1376,8 @@ BinaryenExpressionRef BinaryenAtomicStore(BinaryenModuleRef module, BinaryenExpressionRef ptr, BinaryenExpressionRef value, BinaryenType type, - const char* memoryName) { + const char* memoryName, + BinaryenMemoryOrder order) { return static_cast( Builder(*(Module*)module) .makeAtomicStore(bytes, @@ -1372,7 +1386,7 @@ BinaryenExpressionRef BinaryenAtomicStore(BinaryenModuleRef module, (Expression*)value, Type(type), getMemoryName(module, memoryName), - MemoryOrder::SeqCst)); + static_cast(order))); } BinaryenExpressionRef BinaryenAtomicRMW(BinaryenModuleRef module, BinaryenOp op, @@ -1381,7 +1395,8 @@ BinaryenExpressionRef BinaryenAtomicRMW(BinaryenModuleRef module, BinaryenExpressionRef ptr, BinaryenExpressionRef value, BinaryenType type, - const char* memoryName) { + const char* memoryName, + BinaryenMemoryOrder order) { return Builder(*(Module*)module) .makeAtomicRMW(AtomicRMWOp(op), bytes, @@ -1390,7 +1405,7 @@ BinaryenExpressionRef BinaryenAtomicRMW(BinaryenModuleRef module, (Expression*)value, Type(type), getMemoryName(module, memoryName), - MemoryOrder::SeqCst); + static_cast(order)); } BinaryenExpressionRef BinaryenAtomicCmpxchg(BinaryenModuleRef module, BinaryenIndex bytes, @@ -1399,16 +1414,18 @@ BinaryenExpressionRef BinaryenAtomicCmpxchg(BinaryenModuleRef module, BinaryenExpressionRef expected, BinaryenExpressionRef replacement, BinaryenType type, - const char* memoryName) { - return Builder(*(Module*)module) - .makeAtomicCmpxchg(bytes, - offset, - (Expression*)ptr, - (Expression*)expected, - (Expression*)replacement, - Type(type), - getMemoryName(module, memoryName), - MemoryOrder::SeqCst); + const char* memoryName, + BinaryenMemoryOrder order) { + return static_cast( + Builder(*(Module*)module) + .makeAtomicCmpxchg(bytes, + offset, + (Expression*)ptr, + (Expression*)expected, + (Expression*)replacement, + Type(type), + getMemoryName(module, memoryName), + static_cast(order))); } BinaryenExpressionRef BinaryenAtomicWait(BinaryenModuleRef module, BinaryenExpressionRef ptr, @@ -2647,6 +2664,21 @@ void BinaryenLoadSetAtomic(BinaryenExpressionRef expr, bool isAtomic) { static_cast(expression)->order = isAtomic ? MemoryOrder::SeqCst : MemoryOrder::Unordered; } + +BinaryenMemoryOrder BinaryenLoadGetMemoryOrder(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast( + static_cast(expression)->order); +} + +void BinaryenLoadSetMemoryOrder(BinaryenExpressionRef expr, + BinaryenMemoryOrder order) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->order = static_cast(order); +} + bool BinaryenLoadIsSigned(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); @@ -2711,6 +2743,21 @@ void BinaryenStoreSetAtomic(BinaryenExpressionRef expr, bool isAtomic) { static_cast(expression)->order = isAtomic ? MemoryOrder::SeqCst : MemoryOrder::Unordered; } + +BinaryenMemoryOrder BinaryenStoreGetMemoryOrder(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast( + static_cast(expression)->order); +} + +void BinaryenStoreSetMemoryOrder(BinaryenExpressionRef expr, + BinaryenMemoryOrder order) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->order = static_cast(order); +} + uint32_t BinaryenStoreGetBytes(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is()); @@ -3033,6 +3080,21 @@ void BinaryenAtomicRMWSetValue(BinaryenExpressionRef expr, assert(valueExpr); static_cast(expression)->value = (Expression*)valueExpr; } + +BinaryenMemoryOrder +BinaryenAtomicRMWGetMemoryOrder(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast( + static_cast(expression)->order); +} + +void BinaryenAtomicRMWSetMemoryOrder(BinaryenExpressionRef expr, + BinaryenMemoryOrder order) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->order = static_cast(order); +} // AtomicCmpxchg uint32_t BinaryenAtomicCmpxchgGetBytes(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; @@ -3094,6 +3156,22 @@ void BinaryenAtomicCmpxchgSetReplacement( static_cast(expression)->replacement = (Expression*)replacementExpr; } + +BinaryenMemoryOrder +BinaryenAtomicCmpxchgGetMemoryOrder(BinaryenExpressionRef expr) { + auto* expression = (Expression*)expr; + assert(expression->is()); + return static_cast( + static_cast(expression)->order); +} + +void BinaryenAtomicCmpxchgSetMemoryOrder(BinaryenExpressionRef expr, + BinaryenMemoryOrder order) { + auto* expression = (Expression*)expr; + assert(expression->is()); + static_cast(expression)->order = + static_cast(order); +} // AtomicWait BinaryenExpressionRef BinaryenAtomicWaitGetPtr(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; diff --git a/src/binaryen-c.h b/src/binaryen-c.h index ba0b6009424..806574f744e 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -203,6 +203,19 @@ BINARYEN_API BinaryenExternalKind BinaryenExternalMemory(void); BINARYEN_API BinaryenExternalKind BinaryenExternalGlobal(void); BINARYEN_API BinaryenExternalKind BinaryenExternalTag(void); +// MemoryOrder for atomic operations + +typedef uint8_t BinaryenMemoryOrder; + +BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderUnordered(void); + +// Acquire/Release atomic memory operation; acquire for loads, release for +// stores. +BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderAcqRel(void); + +// Sequentially consistent atomic memory operation. +BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderSeqCst(void); + // Features. Call to get the value of each; you can cache them. Use bitwise // operators to combine and test particular features. @@ -844,12 +857,14 @@ BinaryenMemoryGrow(BinaryenModuleRef module, BINARYEN_API BinaryenExpressionRef BinaryenNop(BinaryenModuleRef module); BINARYEN_API BinaryenExpressionRef BinaryenUnreachable(BinaryenModuleRef module); -BINARYEN_API BinaryenExpressionRef BinaryenAtomicLoad(BinaryenModuleRef module, - uint32_t bytes, - uint32_t offset, - BinaryenType type, - BinaryenExpressionRef ptr, - const char* memoryName); +BINARYEN_API BinaryenExpressionRef +BinaryenAtomicLoad(BinaryenModuleRef module, + uint32_t bytes, + uint32_t offset, + BinaryenType type, + BinaryenExpressionRef ptr, + const char* memoryName, + BinaryenMemoryOrder order); BINARYEN_API BinaryenExpressionRef BinaryenAtomicStore(BinaryenModuleRef module, uint32_t bytes, @@ -857,7 +872,8 @@ BinaryenAtomicStore(BinaryenModuleRef module, BinaryenExpressionRef ptr, BinaryenExpressionRef value, BinaryenType type, - const char* memoryName); + const char* memoryName, + BinaryenMemoryOrder order); BINARYEN_API BinaryenExpressionRef BinaryenAtomicRMW(BinaryenModuleRef module, BinaryenOp op, @@ -866,7 +882,8 @@ BinaryenAtomicRMW(BinaryenModuleRef module, BinaryenExpressionRef ptr, BinaryenExpressionRef value, BinaryenType type, - const char* memoryName); + const char* memoryName, + BinaryenMemoryOrder order); BINARYEN_API BinaryenExpressionRef BinaryenAtomicCmpxchg(BinaryenModuleRef module, BinaryenIndex bytes, @@ -875,7 +892,8 @@ BinaryenAtomicCmpxchg(BinaryenModuleRef module, BinaryenExpressionRef expected, BinaryenExpressionRef replacement, BinaryenType type, - const char* memoryName); + const char* memoryName, + BinaryenMemoryOrder order); BINARYEN_API BinaryenExpressionRef BinaryenAtomicWait(BinaryenModuleRef module, BinaryenExpressionRef ptr, @@ -1536,11 +1554,17 @@ BINARYEN_API void BinaryenMemoryGrowSetDelta(BinaryenExpressionRef expr, // Load -// Gets whether a `load` expression is atomic (is an `atomic.load`). +// Gets whether a `load` expression is atomic (is an `atomic.load`), i.e. has a +// memory order other than Unordered. See also `BinaryenLoadGetMemoryOrder`. BINARYEN_API bool BinaryenLoadIsAtomic(BinaryenExpressionRef expr); -// Sets whether a `load` expression is atomic (is an `atomic.load`). -BINARYEN_API void BinaryenLoadSetAtomic(BinaryenExpressionRef expr, - bool isAtomic); +// Get the (atomic / non-atomic) memory order of a Load. See +// `BinaryenMemoryOrder`. +BINARYEN_API BinaryenMemoryOrder +BinaryenLoadGetMemoryOrder(BinaryenExpressionRef expr); +// Set the (atomic / non-atomic) memory order of a Load. See +// `BinaryenMemoryOrder`. +BINARYEN_API void BinaryenLoadSetMemoryOrder(BinaryenExpressionRef expr, + BinaryenMemoryOrder order); // Gets whether a `load` expression operates on a signed value (`_s`). BINARYEN_API bool BinaryenLoadIsSigned(BinaryenExpressionRef expr); // Sets whether a `load` expression operates on a signed value (`_s`). @@ -1570,11 +1594,17 @@ BINARYEN_API void BinaryenLoadSetPtr(BinaryenExpressionRef expr, // Store -// Gets whether a `store` expression is atomic (is an `atomic.store`). +// Gets whether a `store` expression is atomic (is an `atomic.store`), i.e. as a +// memory order other than Unordered. See also `BinaryenStoreGetMemoryOrder`. BINARYEN_API bool BinaryenStoreIsAtomic(BinaryenExpressionRef expr); -// Sets whether a `store` expression is atomic (is an `atomic.store`). -BINARYEN_API void BinaryenStoreSetAtomic(BinaryenExpressionRef expr, - bool isAtomic); +// Get the (atomic / non-atomic) memory order of a Store. See +// `BinaryenMemoryOrder`. +BINARYEN_API BinaryenMemoryOrder +BinaryenStoreGetMemoryOrder(BinaryenExpressionRef expr); +// Set the (atomic / non-atomic) memory order of a Store. See +// `BinaryenMemoryOrder`. +BINARYEN_API void BinaryenStoreSetMemoryOrder(BinaryenExpressionRef expr, + BinaryenMemoryOrder order); // Gets the number of bytes stored by a `store` expression. BINARYEN_API uint32_t BinaryenStoreGetBytes(BinaryenExpressionRef expr); // Sets the number of bytes stored by a `store` expression. @@ -1756,6 +1786,13 @@ BinaryenAtomicRMWGetValue(BinaryenExpressionRef expr); // Sets the value expression of an atomic read-modify-write expression. BINARYEN_API void BinaryenAtomicRMWSetValue(BinaryenExpressionRef expr, BinaryenExpressionRef valueExpr); +// Gets the memory order of an atomic read-modify-write expression. See +// `BinaryenMemoryOrder`. +BINARYEN_API BinaryenMemoryOrder +BinaryenAtomicRMWGetMemoryOrder(BinaryenExpressionRef expr); +// Sets the atomic memory order of a Store. See `BinaryenMemoryOrder`. +BINARYEN_API void BinaryenAtomicRMWSetMemoryOrder(BinaryenExpressionRef expr, + BinaryenMemoryOrder order); // AtomicCmpxchg @@ -1794,6 +1831,15 @@ BinaryenAtomicCmpxchgGetReplacement(BinaryenExpressionRef expr); BINARYEN_API void BinaryenAtomicCmpxchgSetReplacement(BinaryenExpressionRef expr, BinaryenExpressionRef replacementExpr); +// Gets the memory order of an atomic compare and exchange expression. See +// `BinaryenMemoryOrder`. +BINARYEN_API BinaryenMemoryOrder +BinaryenAtomicCmpxchgGetMemoryOrder(BinaryenExpressionRef expr); +// Sets the memory order of an atomic compare and exchange expression. See +// `BinaryenMemoryOrder`. +BINARYEN_API void +BinaryenAtomicCmpxchgSetMemoryOrder(BinaryenExpressionRef expr, + BinaryenMemoryOrder order); // AtomicWait diff --git a/src/js/binaryen.js-post.js b/src/js/binaryen.js-post.js index e6b5a423f74..948dec21d92 100644 --- a/src/js/binaryen.js-post.js +++ b/src/js/binaryen.js-post.js @@ -157,6 +157,15 @@ function initializeConstants() { Module['ExternalKinds'][name] = Module['External' + name] = Module['_BinaryenExternal' + name](); }); + // MemoryOrder for atomic operations + Module['MemoryOrder'] = {}; + [ 'Unordered', + 'SeqCst', + 'AcqRel' + ].forEach(name => { + Module['MemoryOrder'][name.toLowerCase()] = Module['_BinaryenMemoryOrder' + name]() + }); + // Features Module['Features'] = {}; [ 'MVP', @@ -944,112 +953,112 @@ function wrapModule(module, self = {}) { return Module['_BinaryenBinary'](module, Module['GeUInt32'], left, right); }, 'atomic': { - 'load'(offset, ptr, name) { - return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 4, offset, Module['i32'], ptr, strToStack(name))); + 'load'(offset, ptr, name, order) { + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 4, offset, Module['i32'], ptr, strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'load8_u'(offset, ptr, name) { - return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 1, offset, Module['i32'], ptr, strToStack(name))); + 'load8_u'(offset, ptr, name, order) { + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 1, offset, Module['i32'], ptr, strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, 'load16_u'(offset, ptr, name) { - return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 2, offset, Module['i32'], ptr, strToStack(name))); + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 2, offset, Module['i32'], ptr, strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'store'(offset, ptr, value, name) { - return preserveStack(() => Module['_BinaryenAtomicStore'](module, 4, offset, ptr, value, Module['i32'], strToStack(name))); + 'store'(offset, ptr, value, name, order) { + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 4, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'store8'(offset, ptr, value, name) { - return preserveStack(() => Module['_BinaryenAtomicStore'](module, 1, offset, ptr, value, Module['i32'], strToStack(name))); + 'store8'(offset, ptr, value, name, order) { + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 1, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'store16'(offset, ptr, value, name) { - return preserveStack(() => Module['_BinaryenAtomicStore'](module, 2, offset, ptr, value, Module['i32'], strToStack(name))); + 'store16'(offset, ptr, value, name, order) { + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 2, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, 'rmw': { - 'add'(offset, ptr, value, name) { + 'add'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 4, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 4, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'sub'(offset, ptr, value, name) { + 'sub'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 4, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 4, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'and'(offset, ptr, value, name) { + 'and'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 4, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 4, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'or'(offset, ptr, value, name) { + 'or'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 4, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 4, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xor'(offset, ptr, value, name) { + 'xor'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 4, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 4, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xchg'(offset, ptr, value, name) { + 'xchg'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 4, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 4, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'cmpxchg'(offset, ptr, expected, replacement, name) { + 'cmpxchg'(offset, ptr, expected, replacement, name, order) { return preserveStack(() => - Module['_BinaryenAtomicCmpxchg'](module, 4, offset, ptr, expected, replacement, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicCmpxchg'](module, 4, offset, ptr, expected, replacement, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, }, 'rmw8_u': { - 'add'(offset, ptr, value, name) { + 'add'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 1, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 1, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'sub'(offset, ptr, value, name) { + 'sub'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 1, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 1, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'and'(offset, ptr, value, name) { + 'and'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 1, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 1, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'or'(offset, ptr, value, name) { + 'or'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 1, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 1, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xor'(offset, ptr, value, name) { + 'xor'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 1, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 1, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xchg'(offset, ptr, value, name) { + 'xchg'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 1, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 1, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'cmpxchg'(offset, ptr, expected, replacement, name) { + 'cmpxchg'(offset, ptr, expected, replacement, name, order) { return preserveStack(() => - Module['_BinaryenAtomicCmpxchg'](module, 1, offset, ptr, expected, replacement, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicCmpxchg'](module, 1, offset, ptr, expected, replacement, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, }, 'rmw16_u': { - 'add'(offset, ptr, value, name) { + 'add'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 2, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 2, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'sub'(offset, ptr, value, name) { + 'sub'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 2, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 2, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'and'(offset, ptr, value, name) { + 'and'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 2, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 2, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'or'(offset, ptr, value, name) { + 'or'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 2, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 2, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xor'(offset, ptr, value, name) { + 'xor'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 2, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 2, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xchg'(offset, ptr, value, name) { + 'xchg'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 2, offset, ptr, value, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 2, offset, ptr, value, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'cmpxchg'(offset, ptr, expected, replacement, name) { + 'cmpxchg'(offset, ptr, expected, replacement, name, order) { return preserveStack(() => - Module['_BinaryenAtomicCmpxchg'](module, 2, offset, ptr, expected, replacement, Module['i32'], strToStack(name))); + Module['_BinaryenAtomicCmpxchg'](module, 2, offset, ptr, expected, replacement, Module['i32'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, }, }, @@ -1237,148 +1246,148 @@ function wrapModule(module, self = {}) { return Module['_BinaryenBinary'](module, Module['GeUInt64'], left, right); }, 'atomic': { - 'load'(offset, ptr, name) { - return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 8, offset, Module['i64'], ptr, strToStack(name))); + 'load'(offset, ptr, name, order) { + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 8, offset, Module['i64'], ptr, strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'load8_u'(offset, ptr, name) { - return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 1, offset, Module['i64'], ptr, strToStack(name))); + 'load8_u'(offset, ptr, name, order) { + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 1, offset, Module['i64'], ptr, strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'load16_u'(offset, ptr, name) { - return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 2, offset, Module['i64'], ptr, strToStack(name))); + 'load16_u'(offset, ptr, name, order) { + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 2, offset, Module['i64'], ptr, strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'load32_u'(offset, ptr, name) { - return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 4, offset, Module['i64'], ptr, strToStack(name))); + 'load32_u'(offset, ptr, name, order) { + return preserveStack(() => Module['_BinaryenAtomicLoad'](module, 4, offset, Module['i64'], ptr, strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'store'(offset, ptr, value, name) { - return preserveStack(() => Module['_BinaryenAtomicStore'](module, 8, offset, ptr, value, Module['i64'], strToStack(name))); + 'store'(offset, ptr, value, name, order) { + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 8, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'store8'(offset, ptr, value, name) { - return preserveStack(() => Module['_BinaryenAtomicStore'](module, 1, offset, ptr, value, Module['i64'], strToStack(name))); + 'store8'(offset, ptr, value, name, order) { + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 1, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'store16'(offset, ptr, value, name) { - return preserveStack(() => Module['_BinaryenAtomicStore'](module, 2, offset, ptr, value, Module['i64'], strToStack(name))); + 'store16'(offset, ptr, value, name, order) { + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 2, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'store32'(offset, ptr, value, name) { - return preserveStack(() => Module['_BinaryenAtomicStore'](module, 4, offset, ptr, value, Module['i64'], strToStack(name))); + 'store32'(offset, ptr, value, name, order) { + return preserveStack(() => Module['_BinaryenAtomicStore'](module, 4, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, 'rmw': { - 'add'(offset, ptr, value, name) { + 'add'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 8, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 8, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'sub'(offset, ptr, value, name) { + 'sub'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 8, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 8, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'and'(offset, ptr, value, name) { + 'and'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 8, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 8, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'or'(offset, ptr, value, name) { + 'or'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 8, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 8, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xor'(offset, ptr, value, name) { + 'xor'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 8, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 8, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xchg'(offset, ptr, value, name) { + 'xchg'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 8, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 8, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'cmpxchg'(offset, ptr, expected, replacement, name) { + 'cmpxchg'(offset, ptr, expected, replacement, name, order) { return preserveStack(() => - Module['_BinaryenAtomicCmpxchg'](module, 8, offset, ptr, expected, replacement, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicCmpxchg'](module, 8, offset, ptr, expected, replacement, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, }, 'rmw8_u': { - 'add'(offset, ptr, value, name) { + 'add'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 1, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 1, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'sub'(offset, ptr, value, name) { + 'sub'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 1, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 1, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'and'(offset, ptr, value, name) { + 'and'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 1, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 1, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'or'(offset, ptr, value, name) { + 'or'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 1, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 1, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xor'(offset, ptr, value, name) { + 'xor'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 1, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 1, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xchg'(offset, ptr, value, name) { + 'xchg'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 1, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 1, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'cmpxchg'(offset, ptr, expected, replacement, name) { + 'cmpxchg'(offset, ptr, expected, replacement, name, order) { return preserveStack(() => - Module['_BinaryenAtomicCmpxchg'](module, 1, offset, ptr, expected, replacement, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicCmpxchg'](module, 1, offset, ptr, expected, replacement, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, }, 'rmw16_u': { - 'add'(offset, ptr, value, name) { + 'add'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 2, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 2, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'sub'(offset, ptr, value, name) { + 'sub'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 2, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 2, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'and'(offset, ptr, value, name) { + 'and'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 2, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 2, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'or'(offset, ptr, value, name) { + 'or'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 2, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 2, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xor'(offset, ptr, value, name) { + 'xor'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 2, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 2, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xchg'(offset, ptr, value, name) { + 'xchg'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 2, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 2, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'cmpxchg'(offset, ptr, expected, replacement, name) { + 'cmpxchg'(offset, ptr, expected, replacement, name, order) { return preserveStack(() => - Module['_BinaryenAtomicCmpxchg'](module, 2, offset, ptr, expected, replacement, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicCmpxchg'](module, 2, offset, ptr, expected, replacement, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, }, 'rmw32_u': { - 'add'(offset, ptr, value, name) { + 'add'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 4, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAdd'], 4, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'sub'(offset, ptr, value, name) { + 'sub'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 4, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWSub'], 4, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'and'(offset, ptr, value, name) { + 'and'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 4, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWAnd'], 4, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'or'(offset, ptr, value, name) { + 'or'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 4, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWOr'], 4, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xor'(offset, ptr, value, name) { + 'xor'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 4, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXor'], 4, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'xchg'(offset, ptr, value, name) { + 'xchg'(offset, ptr, value, name, order) { return preserveStack(() => - Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 4, offset, ptr, value, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicRMW'](module, Module['AtomicRMWXchg'], 4, offset, ptr, value, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, - 'cmpxchg'(offset, ptr, expected, replacement, name) { + 'cmpxchg'(offset, ptr, expected, replacement, name, order) { return preserveStack(() => - Module['_BinaryenAtomicCmpxchg'](module, 4, offset, ptr, expected, replacement, Module['i64'], strToStack(name))); + Module['_BinaryenAtomicCmpxchg'](module, 4, offset, ptr, expected, replacement, Module['i64'], strToStack(name), typeof order !== 'undefined' ? order : Module['MemoryOrder']['seqcst'])); }, }, }, @@ -3932,8 +3941,11 @@ Module['Load'] = makeExpressionWrapper(Module['_BinaryenLoadId'](), { 'isAtomic'(expr) { return Boolean(Module['_BinaryenLoadIsAtomic'](expr)); }, - 'setAtomic'(expr, isAtomic) { - Module['_BinaryenLoadSetAtomic'](expr, isAtomic); + 'getMemoryOrder'(expr) { + return Module['_BinaryenLoadGetMemoryOrder'](expr); + }, + 'setMemoryOrder'(expr, order) { + Module['_BinaryenLoadSetMemoryOrder'](expr, order); }, 'isSigned'(expr) { return Boolean(Module['_BinaryenLoadIsSigned'](expr)); @@ -3971,8 +3983,11 @@ Module['Store'] = makeExpressionWrapper(Module['_BinaryenStoreId'](), { 'isAtomic'(expr) { return Boolean(Module['_BinaryenStoreIsAtomic'](expr)); }, - 'setAtomic'(expr, isAtomic) { - Module['_BinaryenStoreSetAtomic'](expr, isAtomic); + 'getMemoryOrder'(expr) { + return Module['_BinaryenStoreGetMemoryOrder'](expr); + }, + 'setMemoryOrder'(expr, order) { + Module['_BinaryenStoreSetMemoryOrder'](expr, order); }, 'getBytes'(expr) { return Module['_BinaryenStoreGetBytes'](expr); @@ -4148,6 +4163,12 @@ Module['AtomicRMW'] = makeExpressionWrapper(Module['_BinaryenAtomicRMWId'](), { 'setOp'(expr, op) { Module['_BinaryenAtomicRMWSetOp'](expr, op); }, + 'getMemoryOrder'(expr) { + return Module['_BinaryenAtomicRMWGetMemoryOrder'](expr); + }, + 'setMemoryOrder'(expr, order) { + Module['_BinaryenAtomicRMWSetMemoryOrder'](expr, order); + }, 'getBytes'(expr) { return Module['_BinaryenAtomicRMWGetBytes'](expr); }, @@ -4175,6 +4196,12 @@ Module['AtomicRMW'] = makeExpressionWrapper(Module['_BinaryenAtomicRMWId'](), { }); Module['AtomicCmpxchg'] = makeExpressionWrapper(Module['_BinaryenAtomicCmpxchgId'](), { + 'getMemoryOrder'(expr) { + return Module['_BinaryenAtomicCmpxchgGetMemoryOrder'](expr); + }, + 'setMemoryOrder'(expr, order) { + Module['_BinaryenAtomicCmpxchgSetMemoryOrder'](expr, order); + }, 'getBytes'(expr) { return Module['_BinaryenAtomicCmpxchgGetBytes'](expr); }, diff --git a/src/wasm.h b/src/wasm.h index 40229970f78..34859cd4971 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -66,7 +66,7 @@ struct Address { } }; -enum class MemoryOrder { +enum class MemoryOrder : uint8_t { Unordered, SeqCst, AcqRel, diff --git a/test/binaryen.js/expressions.js b/test/binaryen.js/expressions.js index ec7f866c535..e28e300721a 100644 --- a/test/binaryen.js/expressions.js +++ b/test/binaryen.js/expressions.js @@ -722,7 +722,7 @@ console.log("# Load"); assert(theLoad.signed === false); theLoad.bytes = 8; assert(theLoad.bytes === 8); - theLoad.atomic = true; + theLoad.memoryOrder = binaryen.MemoryOrder.seqcst; assert(theLoad.atomic === true); theLoad.finalize(); assert(theLoad.align === 4); @@ -791,7 +791,7 @@ console.log("# Store"); assert(theStore.valueType === binaryen.i64); theStore.bytes = 8; assert(theStore.bytes === 8); - theStore.atomic = true; + theStore.memoryOrder = binaryen.MemoryOrder.seqcst; assert(theStore.atomic === true); theStore.finalize(); assert(theStore.align === 4); diff --git a/test/binaryen.js/kitchen-sink.js b/test/binaryen.js/kitchen-sink.js index 6fbe5d171f4..673a470607d 100644 --- a/test/binaryen.js/kitchen-sink.js +++ b/test/binaryen.js/kitchen-sink.js @@ -624,6 +624,16 @@ function test_core() { module.i32.const(0) ) ), + module.i32.atomic.store(0, + module.i32.const(0), + module.i32.atomic.load(0, + module.i32.const(0), + /* name=*/undefined, + binaryen.MemoryOrder.acqrel + ), + /*name=*/undefined, + binaryen.MemoryOrder.acqrel + ), module.drop( module.memory.atomic.wait32( module.i32.const(0), @@ -1167,6 +1177,41 @@ function test_expression_info() { module.dispose(); } +function test_relaxed_atomics() { + module = new binaryen.Module(); + module.setFeatures(binaryen.Features.All); + + module.setMemory(1, 1, "memory", [], false, false, "0"); + + var load = module.i32.load(0, 0, makeInt32(0), "0"); + binaryen.Load.setMemoryOrder(load, binaryen.MemoryOrder.acqrel); + console.log("Load memory order: " + binaryen.Load.getMemoryOrder(load)); + + var store = module.i32.store(0, 0, makeInt32(0), makeInt32(1), "0"); + binaryen.Store.setMemoryOrder(store, binaryen.MemoryOrder.acqrel); + console.log("Store memory order: " + binaryen.Store.getMemoryOrder(store)); + + var rmw = module.i32.atomic.rmw.add(0, makeInt32(0), makeInt32(1), "0", binaryen.MemoryOrder.seqcst); + binaryen.AtomicRMW.setMemoryOrder(rmw, binaryen.MemoryOrder.acqrel); + console.log("RMW memory order: " + binaryen.AtomicRMW.getMemoryOrder(rmw)); + + var cmpxchg = module.i32.atomic.rmw.cmpxchg(0, makeInt32(0), makeInt32(0), makeInt32(1), "0", binaryen.MemoryOrder.seqcst); + binaryen.AtomicCmpxchg.setMemoryOrder(cmpxchg, binaryen.MemoryOrder.acqrel); + console.log("Cmpxchg memory order: " + binaryen.AtomicCmpxchg.getMemoryOrder(cmpxchg)); + + var body = module.block("body", [ + module.drop(load), + store, + module.drop(rmw), + module.drop(cmpxchg) + ], binaryen.auto); + + module.addFunction("relaxed-atomics", binaryen.none, binaryen.none, [], body); + + console.log(module.emitText()); + module.dispose(); +} + test_types(); test_features(); test_ids(); @@ -1179,3 +1224,4 @@ test_parsing(); test_internals(); test_for_each(); test_expression_info(); +test_relaxed_atomics(); diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt index bce7e24e79e..c5ea5bded75 100644 --- a/test/binaryen.js/kitchen-sink.js.txt +++ b/test/binaryen.js/kitchen-sink.js.txt @@ -2120,6 +2120,12 @@ getExpressionInfo(tuple[3])={"id":14,"type":5,"value":3.7} (i32.const 0) ) ) + (i32.atomic.store acqrel + (i32.const 0) + (i32.atomic.load acqrel + (i32.const 0) + ) + ) (drop (memory.atomic.wait32 (i32.const 0) @@ -2826,3 +2832,39 @@ sizeof Literal: 24 getExpressionInfo(memory.grow)={"id":21,"type":2,"delta":1} getExpressionInfo(switch)={"id":5,"type":1,"numNames":1,"names":["label"],"defaultName":"label","condition":0,"value":0} +Load memory order: 2 +Store memory order: 2 +RMW memory order: 2 +Cmpxchg memory order: 2 +(module + (type $0 (func)) + (memory $0 1 1) + (export "memory" (memory $0)) + (func $relaxed-atomics (type $0) + (block $body + (drop + (i32.atomic.load acqrel + (i32.const 0) + ) + ) + (i32.atomic.store acqrel + (i32.const 0) + (i32.const 1) + ) + (drop + (i32.atomic.rmw.add acqrel + (i32.const 0) + (i32.const 1) + ) + ) + (drop + (i32.atomic.rmw.cmpxchg acqrel + (i32.const 0) + (i32.const 0) + (i32.const 1) + ) + ) + ) + ) +) + diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 9a23c82cb5d..2499ffff646 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -1105,9 +1105,16 @@ void test_core() { 4, 0, temp6, - BinaryenAtomicLoad(module, 4, 0, BinaryenTypeInt32(), temp6, "0"), + BinaryenAtomicLoad(module, + 4, + 0, + BinaryenTypeInt32(), + temp6, + "0", + BinaryenMemoryOrderSeqCst()), BinaryenTypeInt32(), - "0"), + "0", + BinaryenMemoryOrderSeqCst()), BinaryenDrop(module, BinaryenAtomicWait( module, temp6, temp6, temp16, BinaryenTypeInt32(), "0")), @@ -2278,6 +2285,77 @@ void test_callref_and_types() { BinaryenModuleDispose(module); } +void test_relaxed_atomics() { + BinaryenModuleRef module = BinaryenModuleCreate(); + BinaryenModuleSetFeatures(module, BinaryenFeatureAll()); + + BinaryenSetMemory( + module, 1, 1, "memory", NULL, NULL, NULL, NULL, NULL, 0, false, false, "0"); + + BinaryenExpressionRef load = BinaryenLoad( + module, 4, 0, 0, 0, BinaryenTypeInt32(), makeInt32(module, 0), "0"); + BinaryenLoadSetMemoryOrder(load, BinaryenMemoryOrderAcqRel()); + printf("Load memory order: %d\n", BinaryenLoadGetMemoryOrder(load)); + + BinaryenExpressionRef store = BinaryenStore(module, + 4, + 0, + 0, + makeInt32(module, 0), + makeInt32(module, 1), + BinaryenTypeInt32(), + "0"); + BinaryenStoreSetMemoryOrder(store, BinaryenMemoryOrderAcqRel()); + printf("Store memory order: %d\n", BinaryenStoreGetMemoryOrder(store)); + + BinaryenExpressionRef rmw = BinaryenAtomicRMW(module, + BinaryenAtomicRMWAdd(), + 4, + 0, + makeInt32(module, 0), + makeInt32(module, 1), + BinaryenTypeInt32(), + "0", + BinaryenMemoryOrderSeqCst()); + BinaryenAtomicRMWSetMemoryOrder(rmw, BinaryenMemoryOrderAcqRel()); + printf("RMW memory order: %d\n", BinaryenAtomicRMWGetMemoryOrder(rmw)); + + BinaryenExpressionRef cmpxchg = + BinaryenAtomicCmpxchg(module, + 4, + 0, + makeInt32(module, 0), + makeInt32(module, 0), + makeInt32(module, 1), + BinaryenTypeInt32(), + "0", + BinaryenMemoryOrderSeqCst()); + BinaryenAtomicCmpxchgSetMemoryOrder(cmpxchg, BinaryenMemoryOrderAcqRel()); + printf("Cmpxchg memory order: %d\n", + BinaryenAtomicCmpxchgGetMemoryOrder(cmpxchg)); + + BinaryenExpressionRef statements[] = {BinaryenDrop(module, load), + store, + BinaryenDrop(module, rmw), + BinaryenDrop(module, cmpxchg)}; + + BinaryenExpressionRef value = + BinaryenBlock(module, + "body", + statements, + sizeof(statements) / sizeof(BinaryenExpressionRef), + BinaryenTypeAuto()); + + BinaryenFunctionRef tiny = BinaryenAddFunction(module, + "relaxed-atomics", + BinaryenTypeNone(), + BinaryenTypeNone(), + NULL, + 0, + value); + BinaryenModulePrint(module); + BinaryenModuleDispose(module); +} int main() { test_types(); test_features(); @@ -2292,6 +2370,7 @@ int main() { test_func_opt(); test_typebuilder(); test_callref_and_types(); + test_relaxed_atomics(); return 0; } diff --git a/test/example/c-api-kitchen-sink.txt b/test/example/c-api-kitchen-sink.txt index 0b4c7d1d887..4d68abcddd5 100644 --- a/test/example/c-api-kitchen-sink.txt +++ b/test/example/c-api-kitchen-sink.txt @@ -3092,3 +3092,38 @@ module with a call_ref: ) ) ) +Load memory order: 2 +Store memory order: 2 +RMW memory order: 2 +Cmpxchg memory order: 2 +(module + (type $0 (func)) + (memory $0 1 1) + (export "memory" (memory $0)) + (func $relaxed-atomics (type $0) + (block $body + (drop + (i32.atomic.load acqrel + (i32.const 0) + ) + ) + (i32.atomic.store acqrel + (i32.const 0) + (i32.const 1) + ) + (drop + (i32.atomic.rmw.add acqrel + (i32.const 0) + (i32.const 1) + ) + ) + (drop + (i32.atomic.rmw.cmpxchg acqrel + (i32.const 0) + (i32.const 0) + (i32.const 1) + ) + ) + ) + ) +)