Skip to content
Open
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
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add PR numbers to each line here.

- 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))
- `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
----
Expand Down
110 changes: 94 additions & 16 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,18 @@ BinaryenExternalKind BinaryenExternalTag(void) {
return static_cast<BinaryenExternalKind>(ExternalKind::Tag);
}

// MemoryOrder for atomic operations

BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderUnordered(void) {
return static_cast<BinaryenMemoryOrder>(MemoryOrder::Unordered);
}
BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderAcqRel(void) {
return static_cast<BinaryenMemoryOrder>(MemoryOrder::AcqRel);
}
BINARYEN_API BinaryenMemoryOrder BinaryenMemoryOrderSeqCst(void) {
return static_cast<BinaryenMemoryOrder>(MemoryOrder::SeqCst);
}

// Features

BinaryenFeatures BinaryenFeatureMVP(void) {
Expand Down Expand Up @@ -1347,23 +1359,25 @@ BinaryenExpressionRef BinaryenAtomicLoad(BinaryenModuleRef module,
uint32_t offset,
BinaryenType type,
BinaryenExpressionRef ptr,
const char* memoryName) {
const char* memoryName,
BinaryenMemoryOrder order) {
return static_cast<Expression*>(
Builder(*(Module*)module)
.makeAtomicLoad(bytes,
offset,
(Expression*)ptr,
Type(type),
getMemoryName(module, memoryName),
MemoryOrder::SeqCst));
static_cast<MemoryOrder>(order)));
}
BinaryenExpressionRef BinaryenAtomicStore(BinaryenModuleRef module,
uint32_t bytes,
uint32_t offset,
BinaryenExpressionRef ptr,
BinaryenExpressionRef value,
BinaryenType type,
const char* memoryName) {
const char* memoryName,
BinaryenMemoryOrder order) {
return static_cast<Expression*>(
Builder(*(Module*)module)
.makeAtomicStore(bytes,
Expand All @@ -1372,7 +1386,7 @@ BinaryenExpressionRef BinaryenAtomicStore(BinaryenModuleRef module,
(Expression*)value,
Type(type),
getMemoryName(module, memoryName),
MemoryOrder::SeqCst));
static_cast<MemoryOrder>(order)));
}
BinaryenExpressionRef BinaryenAtomicRMW(BinaryenModuleRef module,
BinaryenOp op,
Expand All @@ -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,
Expand All @@ -1390,7 +1405,7 @@ BinaryenExpressionRef BinaryenAtomicRMW(BinaryenModuleRef module,
(Expression*)value,
Type(type),
getMemoryName(module, memoryName),
MemoryOrder::SeqCst);
static_cast<MemoryOrder>(order));
}
BinaryenExpressionRef BinaryenAtomicCmpxchg(BinaryenModuleRef module,
BinaryenIndex bytes,
Expand All @@ -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<Expression*>(
Builder(*(Module*)module)
.makeAtomicCmpxchg(bytes,
offset,
(Expression*)ptr,
(Expression*)expected,
(Expression*)replacement,
Type(type),
getMemoryName(module, memoryName),
static_cast<MemoryOrder>(order)));
}
BinaryenExpressionRef BinaryenAtomicWait(BinaryenModuleRef module,
BinaryenExpressionRef ptr,
Expand Down Expand Up @@ -2647,6 +2664,21 @@ void BinaryenLoadSetAtomic(BinaryenExpressionRef expr, bool isAtomic) {
static_cast<Load*>(expression)->order =
isAtomic ? MemoryOrder::SeqCst : MemoryOrder::Unordered;
}

BinaryenMemoryOrder BinaryenLoadGetMemoryOrder(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<Load>());
return static_cast<BinaryenMemoryOrder>(
static_cast<Load*>(expression)->order);
}

void BinaryenLoadSetMemoryOrder(BinaryenExpressionRef expr,
BinaryenMemoryOrder order) {
auto* expression = (Expression*)expr;
assert(expression->is<Load>());
static_cast<Load*>(expression)->order = static_cast<MemoryOrder>(order);
}

bool BinaryenLoadIsSigned(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<Load>());
Expand Down Expand Up @@ -2711,6 +2743,21 @@ void BinaryenStoreSetAtomic(BinaryenExpressionRef expr, bool isAtomic) {
static_cast<Store*>(expression)->order =
isAtomic ? MemoryOrder::SeqCst : MemoryOrder::Unordered;
}

BinaryenMemoryOrder BinaryenStoreGetMemoryOrder(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<Store>());
return static_cast<BinaryenMemoryOrder>(
static_cast<Store*>(expression)->order);
}

void BinaryenStoreSetMemoryOrder(BinaryenExpressionRef expr,
BinaryenMemoryOrder order) {
auto* expression = (Expression*)expr;
assert(expression->is<Store>());
static_cast<Store*>(expression)->order = static_cast<MemoryOrder>(order);
}

uint32_t BinaryenStoreGetBytes(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<Store>());
Expand Down Expand Up @@ -3033,6 +3080,21 @@ void BinaryenAtomicRMWSetValue(BinaryenExpressionRef expr,
assert(valueExpr);
static_cast<AtomicRMW*>(expression)->value = (Expression*)valueExpr;
}

BinaryenMemoryOrder
BinaryenAtomicRMWGetMemoryOrder(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<AtomicRMW>());
return static_cast<BinaryenMemoryOrder>(
static_cast<AtomicRMW*>(expression)->order);
}

void BinaryenAtomicRMWSetMemoryOrder(BinaryenExpressionRef expr,
BinaryenMemoryOrder order) {
auto* expression = (Expression*)expr;
assert(expression->is<AtomicRMW>());
static_cast<AtomicRMW*>(expression)->order = static_cast<MemoryOrder>(order);
}
// AtomicCmpxchg
uint32_t BinaryenAtomicCmpxchgGetBytes(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
Expand Down Expand Up @@ -3094,6 +3156,22 @@ void BinaryenAtomicCmpxchgSetReplacement(
static_cast<AtomicCmpxchg*>(expression)->replacement =
(Expression*)replacementExpr;
}

BinaryenMemoryOrder
BinaryenAtomicCmpxchgGetMemoryOrder(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
assert(expression->is<AtomicCmpxchg>());
return static_cast<BinaryenMemoryOrder>(
static_cast<AtomicCmpxchg*>(expression)->order);
}

void BinaryenAtomicCmpxchgSetMemoryOrder(BinaryenExpressionRef expr,
BinaryenMemoryOrder order) {
auto* expression = (Expression*)expr;
assert(expression->is<AtomicCmpxchg>());
static_cast<AtomicCmpxchg*>(expression)->order =
static_cast<MemoryOrder>(order);
}
// AtomicWait
BinaryenExpressionRef BinaryenAtomicWaitGetPtr(BinaryenExpressionRef expr) {
auto* expression = (Expression*)expr;
Expand Down
80 changes: 63 additions & 17 deletions src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -844,20 +857,23 @@ 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,
uint32_t offset,
BinaryenExpressionRef ptr,
BinaryenExpressionRef value,
BinaryenType type,
const char* memoryName);
const char* memoryName,
BinaryenMemoryOrder order);
BINARYEN_API BinaryenExpressionRef
BinaryenAtomicRMW(BinaryenModuleRef module,
BinaryenOp op,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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`).
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
Loading
Loading