Skip to content
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ full changeset diff at the end of each section.
Current Trunk
-------------

- Added load_splat SIMD instructions
- Binaryen.js instruction API changes:
- `notify` -> `atomic.notify`
- `i32.wait` / `i64.wait` -> `i32.atomic.wait` / `i64.atomic.wait`
Expand Down
22 changes: 22 additions & 0 deletions Contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,25 @@ Interested in participating? Please follow
[the same contributing guidelines as the design repository]: https://github.com/WebAssembly/design/blob/master/Contributing.md

Also, please be sure to read [the README.md](README.md) for this repository.

## Adding support for new instructions

Use this handy checklist to make sure your new instructions are fully supported:

- [ ] Instruction class or opcode added to src/wasm.h
- [ ] Instruction class added to src/wasm-builder.h
- [ ] Instruction class added to src/wasm-traversal.h
- [ ] Validation added to src/wasm/wasm-validator.cpp
- [ ] Interpretation added to src/wasm-interpreter.h
- [ ] Effects handled in src/ir/effects.h
- [ ] Hashing and comparing in src/ir/ExpressionAnalyzer.cpp
- [ ] Parsing added in scripts/gen-s-parser.py and src/wasm/wasm-s-parser.cpp
- [ ] Printing added in src/passes/Print.cpp
- [ ] Decoding added in src/wasm/wasm-binary.cpp
- [ ] Binary writing added in src/wasm-stack.h and src/wasm/wasm-stack.cpp
- [ ] Support added to src/tools/fuzzing.h
- [ ] C API support added in src/binaryen-c.h and src/binaryen-c.cpp
- [ ] JS API support added in build-js.sh and src/js/binaryen.js-post.js
- [ ] C API tested in test/example/c-api-kitchen-sink.c
- [ ] JS API tested in test/binaryen.js/kitchen-sink.js
- [ ] Tests added in test/spec
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice docs!

12 changes: 12 additions & 0 deletions build-js.sh
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export_function "_BinaryenSIMDReplaceId"
export_function "_BinaryenSIMDShuffleId"
export_function "_BinaryenSIMDTernaryId"
export_function "_BinaryenSIMDShiftId"
export_function "_BinaryenSIMDLoadId"
export_function "_BinaryenMemoryInitId"
export_function "_BinaryenDataDropId"
export_function "_BinaryenMemoryCopyId"
Expand Down Expand Up @@ -550,6 +551,10 @@ export_function "_BinaryenConvertSVecI32x4ToVecF32x4"
export_function "_BinaryenConvertUVecI32x4ToVecF32x4"
export_function "_BinaryenConvertSVecI64x2ToVecF64x2"
export_function "_BinaryenConvertUVecI64x2ToVecF64x2"
export_function "_BinaryenLoadSplatVec8x16"
export_function "_BinaryenLoadSplatVec16x8"
export_function "_BinaryenLoadSplatVec32x4"
export_function "_BinaryenLoadSplatVec64x2"
export_function "_BinaryenNarrowSVecI16x8ToVecI8x16"
export_function "_BinaryenNarrowUVecI16x8ToVecI8x16"
export_function "_BinaryenNarrowSVecI32x4ToVecI16x8"
Expand Down Expand Up @@ -601,6 +606,7 @@ export_function "_BinaryenSIMDReplace"
export_function "_BinaryenSIMDShuffle"
export_function "_BinaryenSIMDTernary"
export_function "_BinaryenSIMDShift"
export_function "_BinaryenSIMDLoad"
export_function "_BinaryenMemoryInit"
export_function "_BinaryenDataDrop"
export_function "_BinaryenMemoryCopy"
Expand Down Expand Up @@ -772,6 +778,12 @@ export_function "_BinaryenSIMDShiftGetOp"
export_function "_BinaryenSIMDShiftGetVec"
export_function "_BinaryenSIMDShiftGetShift"

# 'SIMDLoad' expression operations
export_function "_BinaryenSIMDLoadGetOp"
export_function "_BinaryenSIMDLoadGetOffset"
export_function "_BinaryenSIMDLoadGetAlign"
export_function "_BinaryenSIMDLoadGetPtr"

# 'MemoryInit' expression operations
export_function "_BinaryenMemoryInitGetSegment"
export_function "_BinaryenMemoryInitGetDest"
Expand Down
4 changes: 4 additions & 0 deletions scripts/gen-s-parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,10 @@
("f32x4.convert_i32x4_u", "makeUnary(s, UnaryOp::ConvertUVecI32x4ToVecF32x4)"),
("f64x2.convert_i64x2_s", "makeUnary(s, UnaryOp::ConvertSVecI64x2ToVecF64x2)"),
("f64x2.convert_i64x2_u", "makeUnary(s, UnaryOp::ConvertUVecI64x2ToVecF64x2)"),
("v8x16.load_splat", "makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec8x16)"),
("v16x8.load_splat", "makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec16x8)"),
("v32x4.load_splat", "makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec32x4)"),
("v64x2.load_splat", "makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec64x2)"),
("i8x16.narrow_i16x8_s", "makeBinary(s, BinaryOp::NarrowSVecI16x8ToVecI8x16)"),
("i8x16.narrow_i16x8_u", "makeBinary(s, BinaryOp::NarrowUVecI16x8ToVecI8x16)"),
("i16x8.narrow_i32x4_s", "makeBinary(s, BinaryOp::NarrowSVecI32x4ToVecI16x8)"),
Expand Down
62 changes: 62 additions & 0 deletions src/binaryen-c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,9 @@ BinaryenExpressionId BinaryenSIMDTernaryId(void) {
BinaryenExpressionId BinaryenSIMDShiftId(void) {
return Expression::Id::SIMDShiftId;
}
BinaryenExpressionId BinaryenSIMDLoadId(void) {
return Expression::Id::SIMDLoadId;
}
BinaryenExpressionId BinaryenMemoryInitId(void) {
return Expression::Id::MemoryInitId;
}
Expand Down Expand Up @@ -880,6 +883,10 @@ BinaryenOp BinaryenConvertSVecI64x2ToVecF64x2(void) {
BinaryenOp BinaryenConvertUVecI64x2ToVecF64x2(void) {
return ConvertUVecI64x2ToVecF64x2;
}
BinaryenOp BinaryenLoadSplatVec8x16(void) { return LoadSplatVec8x16; }
BinaryenOp BinaryenLoadSplatVec16x8(void) { return LoadSplatVec16x8; }
BinaryenOp BinaryenLoadSplatVec32x4(void) { return LoadSplatVec32x4; }
BinaryenOp BinaryenLoadSplatVec64x2(void) { return LoadSplatVec64x2; }
BinaryenOp BinaryenNarrowSVecI16x8ToVecI8x16(void) {
return NarrowSVecI16x8ToVecI8x16;
}
Expand Down Expand Up @@ -1599,6 +1606,20 @@ BinaryenExpressionRef BinaryenSIMDShift(BinaryenModuleRef module,
}
return static_cast<Expression*>(ret);
}
BinaryenExpressionRef BinaryenSIMDLoad(BinaryenModuleRef module,
BinaryenOp op,
uint32_t offset,
uint32_t align,
BinaryenExpressionRef ptr) {
auto* ret =
Builder(*(Module*)module)
.makeSIMDLoad(
SIMDLoadOp(op), Address(offset), Address(align), (Expression*)ptr);
if (tracing) {
traceExpression(ret, "BinaryenSIMDLoad", op, offset, align, ptr);
}
return static_cast<Expression*>(ret);
}
BinaryenExpressionRef BinaryenMemoryInit(BinaryenModuleRef module,
uint32_t segment,
BinaryenExpressionRef dest,
Expand Down Expand Up @@ -2767,6 +2788,47 @@ BinaryenExpressionRef BinaryenSIMDShiftGetShift(BinaryenExpressionRef expr) {
assert(expression->is<SIMDShift>());
return static_cast<SIMDShift*>(expression)->shift;
}
// SIMDLoad
BinaryenOp BinaryenSIMDLoadGetOp(BinaryenExpressionRef expr) {
if (tracing) {
std::cout << " BinaryenSIMDLoadGetOp(expressions[" << expressions[expr]
<< "])\n";
}

auto* expression = (Expression*)expr;
assert(expression->is<SIMDLoad>());
return static_cast<SIMDLoad*>(expression)->op;
}
uint32_t BinaryenSIMDLoadGetOffset(BinaryenExpressionRef expr) {
if (tracing) {
std::cout << " BinaryenSIMDLoadGetOffset(expressions[" << expressions[expr]
<< "])\n";
}

auto* expression = (Expression*)expr;
assert(expression->is<SIMDLoad>());
return static_cast<SIMDLoad*>(expression)->offset;
}
uint32_t BinaryenSIMDLoadGetAlign(BinaryenExpressionRef expr) {
if (tracing) {
std::cout << " BinaryenSIMDLoadGetAlign(expressions[" << expressions[expr]
<< "])\n";
}

auto* expression = (Expression*)expr;
assert(expression->is<SIMDLoad>());
return static_cast<SIMDLoad*>(expression)->align;
}
BinaryenExpressionRef BinaryenSIMDLoadGetPtr(BinaryenExpressionRef expr) {
if (tracing) {
std::cout << " BinaryenSIMDLoadGetPtr(expressions[" << expressions[expr]
<< "])\n";
}

auto* expression = (Expression*)expr;
assert(expression->is<SIMDLoad>());
return static_cast<SIMDLoad*>(expression)->ptr;
}
// MemoryInit
uint32_t BinaryenMemoryInitGetSegment(BinaryenExpressionRef expr) {
if (tracing) {
Expand Down
16 changes: 16 additions & 0 deletions src/binaryen-c.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ BINARYEN_API BinaryenExpressionId BinaryenSIMDReplaceId(void);
BINARYEN_API BinaryenExpressionId BinaryenSIMDShuffleId(void);
BINARYEN_API BinaryenExpressionId BinaryenSIMDTernaryId(void);
BINARYEN_API BinaryenExpressionId BinaryenSIMDShiftId(void);
BINARYEN_API BinaryenExpressionId BinaryenSIMDLoadId(void);
BINARYEN_API BinaryenExpressionId BinaryenMemoryInitId(void);
BINARYEN_API BinaryenExpressionId BinaryenDataDropId(void);
BINARYEN_API BinaryenExpressionId BinaryenMemoryCopyId(void);
Expand Down Expand Up @@ -522,6 +523,10 @@ BINARYEN_API BinaryenOp BinaryenConvertSVecI32x4ToVecF32x4(void);
BINARYEN_API BinaryenOp BinaryenConvertUVecI32x4ToVecF32x4(void);
BINARYEN_API BinaryenOp BinaryenConvertSVecI64x2ToVecF64x2(void);
BINARYEN_API BinaryenOp BinaryenConvertUVecI64x2ToVecF64x2(void);
BINARYEN_API BinaryenOp BinaryenLoadSplatVec8x16(void);
BINARYEN_API BinaryenOp BinaryenLoadSplatVec16x8(void);
BINARYEN_API BinaryenOp BinaryenLoadSplatVec32x4(void);
BINARYEN_API BinaryenOp BinaryenLoadSplatVec64x2(void);
BINARYEN_API BinaryenOp BinaryenNarrowSVecI16x8ToVecI8x16(void);
BINARYEN_API BinaryenOp BinaryenNarrowUVecI16x8ToVecI8x16(void);
BINARYEN_API BinaryenOp BinaryenNarrowSVecI32x4ToVecI16x8(void);
Expand Down Expand Up @@ -736,6 +741,11 @@ BinaryenSIMDShift(BinaryenModuleRef module,
BinaryenOp op,
BinaryenExpressionRef vec,
BinaryenExpressionRef shift);
BINARYEN_API BinaryenExpressionRef BinaryenSIMDLoad(BinaryenModuleRef module,
BinaryenOp op,
uint32_t offset,
uint32_t align,
BinaryenExpressionRef ptr);
BINARYEN_API BinaryenExpressionRef
BinaryenMemoryInit(BinaryenModuleRef module,
uint32_t segment,
Expand Down Expand Up @@ -962,6 +972,12 @@ BinaryenSIMDShiftGetVec(BinaryenExpressionRef expr);
BINARYEN_API BinaryenExpressionRef
BinaryenSIMDShiftGetShift(BinaryenExpressionRef expr);

BINARYEN_API BinaryenOp BinaryenSIMDLoadGetOp(BinaryenExpressionRef expr);
BINARYEN_API uint32_t BinaryenSIMDLoadGetOffset(BinaryenExpressionRef expr);
BINARYEN_API uint32_t BinaryenSIMDLoadGetAlign(BinaryenExpressionRef expr);
BINARYEN_API BinaryenExpressionRef
BinaryenSIMDLoadGetPtr(BinaryenExpressionRef expr);

BINARYEN_API uint32_t BinaryenMemoryInitGetSegment(BinaryenExpressionRef expr);
BINARYEN_API BinaryenExpressionRef
BinaryenMemoryInitGetDest(BinaryenExpressionRef expr);
Expand Down
74 changes: 48 additions & 26 deletions src/gen-s-parser.inc
Original file line number Diff line number Diff line change
Expand Up @@ -2418,40 +2418,62 @@ switch (op[0]) {
case 'v': {
switch (op[1]) {
case '1': {
switch (op[5]) {
case 'a':
if (strcmp(op, "v128.and") == 0) { return makeBinary(s, BinaryOp::AndVec128); }
goto parse_error;
case 'b':
if (strcmp(op, "v128.bitselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::Bitselect); }
goto parse_error;
case 'c':
if (strcmp(op, "v128.const") == 0) { return makeConst(s, v128); }
switch (op[2]) {
case '2': {
switch (op[5]) {
case 'a':
if (strcmp(op, "v128.and") == 0) { return makeBinary(s, BinaryOp::AndVec128); }
goto parse_error;
case 'b':
if (strcmp(op, "v128.bitselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::Bitselect); }
goto parse_error;
case 'c':
if (strcmp(op, "v128.const") == 0) { return makeConst(s, v128); }
goto parse_error;
case 'l':
if (strcmp(op, "v128.load") == 0) { return makeLoad(s, v128, /*isAtomic=*/false); }
goto parse_error;
case 'n':
if (strcmp(op, "v128.not") == 0) { return makeUnary(s, UnaryOp::NotVec128); }
goto parse_error;
case 'o':
if (strcmp(op, "v128.or") == 0) { return makeBinary(s, BinaryOp::OrVec128); }
goto parse_error;
case 'p':
if (strcmp(op, "v128.pop") == 0) { return makePop(v128); }
goto parse_error;
case 's':
if (strcmp(op, "v128.store") == 0) { return makeStore(s, v128, /*isAtomic=*/false); }
goto parse_error;
case 'x':
if (strcmp(op, "v128.xor") == 0) { return makeBinary(s, BinaryOp::XorVec128); }
goto parse_error;
default: goto parse_error;
}
}
case '6':
if (strcmp(op, "v16x8.load_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec16x8); }
goto parse_error;
default: goto parse_error;
}
}
case '3':
if (strcmp(op, "v32x4.load_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec32x4); }
goto parse_error;
case '6':
if (strcmp(op, "v64x2.load_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec64x2); }
goto parse_error;
case '8': {
switch (op[6]) {
case 'l':
if (strcmp(op, "v128.load") == 0) { return makeLoad(s, v128, /*isAtomic=*/false); }
goto parse_error;
case 'n':
if (strcmp(op, "v128.not") == 0) { return makeUnary(s, UnaryOp::NotVec128); }
goto parse_error;
case 'o':
if (strcmp(op, "v128.or") == 0) { return makeBinary(s, BinaryOp::OrVec128); }
goto parse_error;
case 'p':
if (strcmp(op, "v128.pop") == 0) { return makePop(v128); }
if (strcmp(op, "v8x16.load_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::LoadSplatVec8x16); }
goto parse_error;
case 's':
if (strcmp(op, "v128.store") == 0) { return makeStore(s, v128, /*isAtomic=*/false); }
goto parse_error;
case 'x':
if (strcmp(op, "v128.xor") == 0) { return makeBinary(s, BinaryOp::XorVec128); }
if (strcmp(op, "v8x16.shuffle") == 0) { return makeSIMDShuffle(s); }
goto parse_error;
default: goto parse_error;
}
}
case '8':
if (strcmp(op, "v8x16.shuffle") == 0) { return makeSIMDShuffle(s); }
goto parse_error;
default: goto parse_error;
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/ir/ExpressionAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ template<typename T> void visitImmediates(Expression* curr, T& visitor) {
}
void visitSIMDTernary(SIMDTernary* curr) { visitor.visitInt(curr->op); }
void visitSIMDShift(SIMDShift* curr) { visitor.visitInt(curr->op); }
void visitSIMDLoad(SIMDLoad* curr) {
visitor.visitInt(curr->op);
visitor.visitAddress(curr->offset);
visitor.visitAddress(curr->align);
}
void visitMemoryInit(MemoryInit* curr) {
visitor.visitIndex(curr->segment);
}
Expand Down
4 changes: 4 additions & 0 deletions src/ir/ExpressionManipulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
return builder.makeSIMDShift(
curr->op, copy(curr->vec), copy(curr->shift));
}
Expression* visitSIMDLoad(SIMDLoad* curr) {
return builder.makeSIMDLoad(
curr->op, curr->offset, curr->align, copy(curr->ptr));
}
Expression* visitConst(Const* curr) {
return builder.makeConst(curr->value);
}
Expand Down
1 change: 1 addition & 0 deletions src/ir/ReFinalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ void ReFinalize::visitSIMDReplace(SIMDReplace* curr) { curr->finalize(); }
void ReFinalize::visitSIMDShuffle(SIMDShuffle* curr) { curr->finalize(); }
void ReFinalize::visitSIMDTernary(SIMDTernary* curr) { curr->finalize(); }
void ReFinalize::visitSIMDShift(SIMDShift* curr) { curr->finalize(); }
void ReFinalize::visitSIMDLoad(SIMDLoad* curr) { curr->finalize(); }
void ReFinalize::visitMemoryInit(MemoryInit* curr) { curr->finalize(); }
void ReFinalize::visitDataDrop(DataDrop* curr) { curr->finalize(); }
void ReFinalize::visitMemoryCopy(MemoryCopy* curr) { curr->finalize(); }
Expand Down
6 changes: 6 additions & 0 deletions src/ir/effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,12 @@ struct EffectAnalyzer
void visitSIMDShuffle(SIMDShuffle* curr) {}
void visitSIMDTernary(SIMDTernary* curr) {}
void visitSIMDShift(SIMDShift* curr) {}
void visitSIMDLoad(SIMDLoad* curr) {
readsMemory = true;
if (!ignoreImplicitTraps) {
implicitTrap = true;
}
}
void visitMemoryInit(MemoryInit* curr) {
writesMemory = true;
if (!ignoreImplicitTraps) {
Expand Down
2 changes: 2 additions & 0 deletions src/ir/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct ReFinalize
void visitSIMDShuffle(SIMDShuffle* curr);
void visitSIMDTernary(SIMDTernary* curr);
void visitSIMDShift(SIMDShift* curr);
void visitSIMDLoad(SIMDLoad* curr);
void visitMemoryInit(MemoryInit* curr);
void visitDataDrop(DataDrop* curr);
void visitMemoryCopy(MemoryCopy* curr);
Expand Down Expand Up @@ -198,6 +199,7 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
void visitSIMDShuffle(SIMDShuffle* curr) { curr->finalize(); }
void visitSIMDTernary(SIMDTernary* curr) { curr->finalize(); }
void visitSIMDShift(SIMDShift* curr) { curr->finalize(); }
void visitSIMDLoad(SIMDLoad* curr) { curr->finalize(); }
void visitMemoryInit(MemoryInit* curr) { curr->finalize(); }
void visitDataDrop(DataDrop* curr) { curr->finalize(); }
void visitMemoryCopy(MemoryCopy* curr) { curr->finalize(); }
Expand Down
Loading