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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ full changeset diff at the end of each section.
Current Trunk
-------------

- Reject non-natural alignment for atomic memory operations at parse time (#8962)

v132
----

Expand Down
3 changes: 0 additions & 3 deletions scripts/test/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,9 +415,6 @@ def get_tests(test_dir, extensions=[], recursive=False):

# Requires better support for multi-threaded tests
'threads/wait_notify.wast',

# Non-natural alignment is invalid for atomic operations
'threads/atomic.wast',
]
SPEC_TESTSUITE_PROPOSALS_TO_SKIP = [
]
Expand Down
31 changes: 21 additions & 10 deletions src/parser/contexts.h
Original file line number Diff line number Diff line change
Expand Up @@ -2394,8 +2394,9 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
auto m = getMemory(pos, mem);
CHECK_ERR(m);
if (isAtomic) {
return withLoc(
pos, irBuilder.makeAtomicLoad(bytes, memarg.offset, type, *m, order));
return withLoc(pos,
irBuilder.makeAtomicLoad(
bytes, memarg.offset, memarg.align, type, *m, order));
}
return withLoc(pos,
irBuilder.makeLoad(
Expand All @@ -2413,8 +2414,9 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
auto m = getMemory(pos, mem);
CHECK_ERR(m);
if (isAtomic) {
return withLoc(
pos, irBuilder.makeAtomicStore(bytes, memarg.offset, type, *m, order));
return withLoc(pos,
irBuilder.makeAtomicStore(
bytes, memarg.offset, memarg.align, type, *m, order));
}
return withLoc(
pos, irBuilder.makeStore(bytes, memarg.offset, memarg.align, type, *m));
Expand Down Expand Up @@ -2454,8 +2456,14 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
MemoryOrder order) {
auto m = getMemory(pos, mem);
CHECK_ERR(m);
return withLoc(
pos, irBuilder.makeAtomicRMW(op, bytes, memarg.offset, type, *m, order));
return withLoc(pos,
irBuilder.makeAtomicRMW(op,
bytes,
memarg.offset,
memarg.align,
type,
*m,
order));
}

Result<> makeAtomicCmpxchg(Index pos,
Expand All @@ -2467,8 +2475,9 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
MemoryOrder order) {
auto m = getMemory(pos, mem);
CHECK_ERR(m);
return withLoc(
pos, irBuilder.makeAtomicCmpxchg(bytes, memarg.offset, type, *m, order));
return withLoc(pos,
irBuilder.makeAtomicCmpxchg(
bytes, memarg.offset, memarg.align, type, *m, order));
}

Result<> makeAtomicWait(Index pos,
Expand All @@ -2478,7 +2487,8 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
Memarg memarg) {
auto m = getMemory(pos, mem);
CHECK_ERR(m);
return withLoc(pos, irBuilder.makeAtomicWait(type, memarg.offset, *m));
return withLoc(
pos, irBuilder.makeAtomicWait(type, memarg.offset, memarg.align, *m));
}

Result<> makeAtomicNotify(Index pos,
Expand All @@ -2487,7 +2497,8 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx>, AnnotationParserCtx {
Memarg memarg) {
auto m = getMemory(pos, mem);
CHECK_ERR(m);
return withLoc(pos, irBuilder.makeAtomicNotify(memarg.offset, *m));
return withLoc(
pos, irBuilder.makeAtomicNotify(memarg.offset, memarg.align, *m));
}

Result<> makeAtomicFence(Index pos,
Expand Down
14 changes: 12 additions & 2 deletions src/passes/DeAlign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,19 @@ struct DeAlign : public WalkerPass<PostWalker<DeAlign>> {
return std::make_unique<DeAlign>();
}

void visitLoad(Load* curr) { curr->align = 1; }
void visitLoad(Load* curr) {
if (curr->isAtomic()) {
return;
}
curr->align = 1;
}

void visitStore(Store* curr) { curr->align = 1; }
void visitStore(Store* curr) {
if (curr->isAtomic()) {
return;
}
curr->align = 1;
}

void visitSIMDLoad(SIMDLoad* curr) { curr->align = 1; }

Expand Down
29 changes: 21 additions & 8 deletions src/wasm-ir-builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,20 +155,33 @@ class IRBuilder : public UnifiedExpressionVisitor<IRBuilder, Result<>> {
Name mem);
Result<> makeStore(
unsigned bytes, Address offset, unsigned align, Type type, Name mem);
Result<> makeAtomicLoad(
unsigned bytes, Address offset, Type type, Name mem, MemoryOrder order);
Result<> makeAtomicStore(
unsigned bytes, Address offset, Type type, Name mem, MemoryOrder order);
Result<> makeAtomicLoad(unsigned bytes,
Address offset,
Address align,
Type type,
Name mem,
MemoryOrder order);
Result<> makeAtomicStore(unsigned bytes,
Address offset,
Address align,
Type type,
Name mem,
MemoryOrder order);
Result<> makeAtomicRMW(AtomicRMWOp op,
unsigned bytes,
Address offset,
Address align,
Type type,
Name mem,
MemoryOrder order);
Result<> makeAtomicCmpxchg(
unsigned bytes, Address offset, Type type, Name mem, MemoryOrder order);
Result<> makeAtomicWait(Type type, Address offset, Name mem);
Result<> makeAtomicNotify(Address offset, Name mem);
Result<> makeAtomicCmpxchg(unsigned bytes,
Address offset,
Address align,
Type type,
Name mem,
MemoryOrder order);
Result<> makeAtomicWait(Type type, Address offset, Address align, Name mem);
Result<> makeAtomicNotify(Address offset, Address align, Name mem);
Result<> makeAtomicFence(MemoryOrder order);
Result<> makePause();
Result<> makeSIMDExtract(SIMDExtractOp op, uint8_t lane);
Expand Down
72 changes: 39 additions & 33 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3934,105 +3934,111 @@ Result<> WasmBinaryReader::readInst() {
auto op = getU32LEB();
switch (op) {
case BinaryConsts::I32AtomicLoad8U: {
// TODO: pass align through for validation.
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicLoad(1, offset, Type::i32, mem, memoryOrder);
return builder.makeAtomicLoad(
1, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I32AtomicLoad16U: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicLoad(2, offset, Type::i32, mem, memoryOrder);
return builder.makeAtomicLoad(
2, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I32AtomicLoad: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicLoad(4, offset, Type::i32, mem, memoryOrder);
return builder.makeAtomicLoad(
4, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I64AtomicLoad8U: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicLoad(1, offset, Type::i64, mem, memoryOrder);
return builder.makeAtomicLoad(
1, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicLoad16U: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicLoad(2, offset, Type::i64, mem, memoryOrder);
return builder.makeAtomicLoad(
2, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicLoad32U: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicLoad(4, offset, Type::i64, mem, memoryOrder);
return builder.makeAtomicLoad(
4, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicLoad: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicLoad(8, offset, Type::i64, mem, memoryOrder);
return builder.makeAtomicLoad(
8, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I32AtomicStore8: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicStore(
1, offset, Type::i32, mem, memoryOrder);
1, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I32AtomicStore16: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicStore(
2, offset, Type::i32, mem, memoryOrder);
2, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I32AtomicStore: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicStore(
4, offset, Type::i32, mem, memoryOrder);
4, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I64AtomicStore8: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicStore(
1, offset, Type::i64, mem, memoryOrder);
1, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicStore16: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicStore(
2, offset, Type::i64, mem, memoryOrder);
2, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicStore32: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicStore(
4, offset, Type::i64, mem, memoryOrder);
4, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicStore: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicStore(
8, offset, Type::i64, mem, memoryOrder);
8, offset, align, Type::i64, mem, memoryOrder);
}

#define RMW(op) \
case BinaryConsts::I32AtomicRMW##op: { \
auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \
return builder.makeAtomicRMW( \
RMW##op, 4, offset, Type::i32, mem, memoryOrder); \
return builder.makeAtomicRMW( \
RMW##op, 4, offset, align, Type::i32, mem, memoryOrder); \
} \
case BinaryConsts::I32AtomicRMW##op##8U: { \
auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \
return builder.makeAtomicRMW( \
RMW##op, 1, offset, Type::i32, mem, memoryOrder); \
RMW##op, 1, offset, align, Type::i32, mem, memoryOrder); \
} \
case BinaryConsts::I32AtomicRMW##op##16U: { \
auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \
return builder.makeAtomicRMW( \
RMW##op, 2, offset, Type::i32, mem, memoryOrder); \
RMW##op, 2, offset, align, Type::i32, mem, memoryOrder); \
} \
case BinaryConsts::I64AtomicRMW##op: { \
auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \
return builder.makeAtomicRMW( \
RMW##op, 8, offset, Type::i64, mem, memoryOrder); \
RMW##op, 8, offset, align, Type::i64, mem, memoryOrder); \
} \
case BinaryConsts::I64AtomicRMW##op##8U: { \
auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \
return builder.makeAtomicRMW( \
RMW##op, 1, offset, Type::i64, mem, memoryOrder); \
RMW##op, 1, offset, align, Type::i64, mem, memoryOrder); \
} \
case BinaryConsts::I64AtomicRMW##op##16U: { \
auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \
return builder.makeAtomicRMW( \
RMW##op, 2, offset, Type::i64, mem, memoryOrder); \
RMW##op, 2, offset, align, Type::i64, mem, memoryOrder); \
} \
case BinaryConsts::I64AtomicRMW##op##32U: { \
auto [mem, align, offset, memoryOrder] = getRMWMemarg(); \
return builder.makeAtomicRMW( \
RMW##op, 4, offset, Type::i64, mem, memoryOrder); \
RMW##op, 4, offset, align, Type::i64, mem, memoryOrder); \
}

RMW(Add);
Expand All @@ -4045,49 +4051,49 @@ Result<> WasmBinaryReader::readInst() {
case BinaryConsts::I32AtomicCmpxchg: {
auto [mem, align, offset, memoryOrder] = getRMWMemarg();
return builder.makeAtomicCmpxchg(
4, offset, Type::i32, mem, memoryOrder);
4, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I32AtomicCmpxchg8U: {
auto [mem, align, offset, memoryOrder] = getRMWMemarg();
return builder.makeAtomicCmpxchg(
1, offset, Type::i32, mem, memoryOrder);
1, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I32AtomicCmpxchg16U: {
auto [mem, align, offset, memoryOrder] = getRMWMemarg();
return builder.makeAtomicCmpxchg(
2, offset, Type::i32, mem, memoryOrder);
2, offset, align, Type::i32, mem, memoryOrder);
}
case BinaryConsts::I64AtomicCmpxchg: {
auto [mem, align, offset, memoryOrder] = getRMWMemarg();
return builder.makeAtomicCmpxchg(
8, offset, Type::i64, mem, memoryOrder);
8, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicCmpxchg8U: {
auto [mem, align, offset, memoryOrder] = getRMWMemarg();
return builder.makeAtomicCmpxchg(
1, offset, Type::i64, mem, memoryOrder);
1, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicCmpxchg16U: {
auto [mem, align, offset, memoryOrder] = getRMWMemarg();
return builder.makeAtomicCmpxchg(
2, offset, Type::i64, mem, memoryOrder);
2, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I64AtomicCmpxchg32U: {
auto [mem, align, offset, memoryOrder] = getRMWMemarg();
return builder.makeAtomicCmpxchg(
4, offset, Type::i64, mem, memoryOrder);
4, offset, align, Type::i64, mem, memoryOrder);
}
case BinaryConsts::I32AtomicWait: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicWait(Type::i32, offset, mem);
return builder.makeAtomicWait(Type::i32, offset, align, mem);
}
case BinaryConsts::I64AtomicWait: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicWait(Type::i64, offset, mem);
return builder.makeAtomicWait(Type::i64, offset, align, mem);
}
case BinaryConsts::AtomicNotify: {
auto [mem, align, offset, memoryOrder] = getAtomicMemarg();
return builder.makeAtomicNotify(offset, mem);
return builder.makeAtomicNotify(offset, align, mem);
}
case BinaryConsts::AtomicFence: {
MemoryOrder order = getMemoryOrder(/*isRMW=*/false);
Expand Down
Loading
Loading