summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/gen-s-parser.py8
-rw-r--r--src/binaryen-c.h1
-rw-r--r--src/gen-s-parser.inc53
-rw-r--r--src/ir/ExpressionAnalyzer.cpp6
-rw-r--r--src/ir/ExpressionManipulator.cpp8
-rw-r--r--src/ir/ReFinalize.cpp3
-rw-r--r--src/ir/effects.h10
-rw-r--r--src/ir/utils.h2
-rw-r--r--src/passes/DeadCodeElimination.cpp2
-rw-r--r--src/passes/Print.cpp45
-rw-r--r--src/tools/fuzzing.h1
-rw-r--r--src/wasm-binary.h10
-rw-r--r--src/wasm-builder.h16
-rw-r--r--src/wasm-interpreter.h79
-rw-r--r--src/wasm-s-parser.h1
-rw-r--r--src/wasm-stack.h1
-rw-r--r--src/wasm-traversal.h15
-rw-r--r--src/wasm.h33
-rw-r--r--src/wasm/wasm-binary.cpp54
-rw-r--r--src/wasm/wasm-s-parser.cpp43
-rw-r--r--src/wasm/wasm-stack.cpp33
-rw-r--r--src/wasm/wasm-validator.cpp54
-rw-r--r--src/wasm/wasm.cpp44
-rw-r--r--src/wasm2js.h4
-rw-r--r--test/binaryen.js/exception-handling.js.txt8
-rw-r--r--test/binaryen.js/kitchen-sink.js.txt58
-rw-r--r--test/simd.wast84
-rw-r--r--test/simd.wast.from-wast87
-rw-r--r--test/simd.wast.fromBinary87
-rw-r--r--test/simd.wast.fromBinary.noDebugInfo351
-rw-r--r--test/spec/simd.wast59
31 files changed, 1083 insertions, 177 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py
index 4c33fcf78..7fd3d1ec6 100755
--- a/scripts/gen-s-parser.py
+++ b/scripts/gen-s-parser.py
@@ -350,6 +350,14 @@ instructions = [
("v128.xor", "makeBinary(s, BinaryOp::XorVec128)"),
("v128.andnot", "makeBinary(s, BinaryOp::AndNotVec128)"),
("v128.bitselect", "makeSIMDTernary(s, SIMDTernaryOp::Bitselect)"),
+ ("v128.load8_lane", "makeSIMDLoadStoreLane(s, LoadLaneVec8x16)"),
+ ("v128.load16_lane", "makeSIMDLoadStoreLane(s, LoadLaneVec16x8)"),
+ ("v128.load32_lane", "makeSIMDLoadStoreLane(s, LoadLaneVec32x4)"),
+ ("v128.load64_lane", "makeSIMDLoadStoreLane(s, LoadLaneVec64x2)"),
+ ("v128.store8_lane", "makeSIMDLoadStoreLane(s, StoreLaneVec8x16)"),
+ ("v128.store16_lane", "makeSIMDLoadStoreLane(s, StoreLaneVec16x8)"),
+ ("v128.store32_lane", "makeSIMDLoadStoreLane(s, StoreLaneVec32x4)"),
+ ("v128.store64_lane", "makeSIMDLoadStoreLane(s, StoreLaneVec64x2)"),
("i8x16.abs", "makeUnary(s, UnaryOp::AbsVecI8x16)"),
("i8x16.neg", "makeUnary(s, UnaryOp::NegVecI8x16)"),
("i8x16.any_true", "makeUnary(s, UnaryOp::AnyTrueVecI8x16)"),
diff --git a/src/binaryen-c.h b/src/binaryen-c.h
index 8713d8f63..ecf0027f3 100644
--- a/src/binaryen-c.h
+++ b/src/binaryen-c.h
@@ -159,6 +159,7 @@ BINARYEN_API BinaryenExpressionId BinaryenSIMDShuffleId(void);
BINARYEN_API BinaryenExpressionId BinaryenSIMDTernaryId(void);
BINARYEN_API BinaryenExpressionId BinaryenSIMDShiftId(void);
BINARYEN_API BinaryenExpressionId BinaryenSIMDLoadId(void);
+// TODO: Expose SIMDLoadStoreLane in C and JS APIs
BINARYEN_API BinaryenExpressionId BinaryenMemoryInitId(void);
BINARYEN_API BinaryenExpressionId BinaryenDataDropId(void);
BINARYEN_API BinaryenExpressionId BinaryenMemoryCopyId(void);
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
index 8a2c9163c..2bbcde499 100644
--- a/src/gen-s-parser.inc
+++ b/src/gen-s-parser.inc
@@ -2776,11 +2776,33 @@ switch (op[0]) {
case '\0':
if (strcmp(op, "v128.load") == 0) { return makeLoad(s, Type::v128, /*isAtomic=*/false); }
goto parse_error;
- case '3':
- if (strcmp(op, "v128.load32_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32Zero); }
+ case '1':
+ if (strcmp(op, "v128.load16_lane") == 0) { return makeSIMDLoadStoreLane(s, LoadLaneVec16x8); }
goto parse_error;
- case '6':
- if (strcmp(op, "v128.load64_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load64Zero); }
+ case '3': {
+ switch (op[12]) {
+ case 'l':
+ if (strcmp(op, "v128.load32_lane") == 0) { return makeSIMDLoadStoreLane(s, LoadLaneVec32x4); }
+ goto parse_error;
+ case 'z':
+ if (strcmp(op, "v128.load32_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32Zero); }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[12]) {
+ case 'l':
+ if (strcmp(op, "v128.load64_lane") == 0) { return makeSIMDLoadStoreLane(s, LoadLaneVec64x2); }
+ goto parse_error;
+ case 'z':
+ if (strcmp(op, "v128.load64_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load64Zero); }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
+ case '8':
+ if (strcmp(op, "v128.load8_lane") == 0) { return makeSIMDLoadStoreLane(s, LoadLaneVec8x16); }
goto parse_error;
default: goto parse_error;
}
@@ -2791,9 +2813,26 @@ switch (op[0]) {
case 'o':
if (strcmp(op, "v128.or") == 0) { return makeBinary(s, BinaryOp::OrVec128); }
goto parse_error;
- case 's':
- if (strcmp(op, "v128.store") == 0) { return makeStore(s, Type::v128, /*isAtomic=*/false); }
- goto parse_error;
+ case 's': {
+ switch (op[10]) {
+ case '\0':
+ if (strcmp(op, "v128.store") == 0) { return makeStore(s, Type::v128, /*isAtomic=*/false); }
+ goto parse_error;
+ case '1':
+ if (strcmp(op, "v128.store16_lane") == 0) { return makeSIMDLoadStoreLane(s, StoreLaneVec16x8); }
+ goto parse_error;
+ case '3':
+ if (strcmp(op, "v128.store32_lane") == 0) { return makeSIMDLoadStoreLane(s, StoreLaneVec32x4); }
+ goto parse_error;
+ case '6':
+ if (strcmp(op, "v128.store64_lane") == 0) { return makeSIMDLoadStoreLane(s, StoreLaneVec64x2); }
+ goto parse_error;
+ case '8':
+ if (strcmp(op, "v128.store8_lane") == 0) { return makeSIMDLoadStoreLane(s, StoreLaneVec8x16); }
+ goto parse_error;
+ default: goto parse_error;
+ }
+ }
case 'x':
if (strcmp(op, "v128.xor") == 0) { return makeBinary(s, BinaryOp::XorVec128); }
goto parse_error;
diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp
index 9b0bdd007..043fb259b 100644
--- a/src/ir/ExpressionAnalyzer.cpp
+++ b/src/ir/ExpressionAnalyzer.cpp
@@ -203,6 +203,12 @@ template<typename T> void visitImmediates(Expression* curr, T& visitor) {
visitor.visitAddress(curr->offset);
visitor.visitAddress(curr->align);
}
+ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ visitor.visitInt(curr->op);
+ visitor.visitAddress(curr->offset);
+ visitor.visitAddress(curr->align);
+ visitor.visitInt(curr->index);
+ }
void visitMemoryInit(MemoryInit* curr) {
visitor.visitIndex(curr->segment);
}
diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp
index 5fb98d86a..648a872fc 100644
--- a/src/ir/ExpressionManipulator.cpp
+++ b/src/ir/ExpressionManipulator.cpp
@@ -182,6 +182,14 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) {
return builder.makeSIMDLoad(
curr->op, curr->offset, curr->align, copy(curr->ptr));
}
+ Expression* visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ return builder.makeSIMDLoadStoreLane(curr->op,
+ curr->offset,
+ curr->align,
+ curr->index,
+ copy(curr->ptr),
+ copy(curr->vec));
+ }
Expression* visitConst(Const* curr) {
return builder.makeConst(curr->value);
}
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index c3516be0a..19fed54a7 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -109,6 +109,9 @@ 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::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ curr->finalize();
+}
void ReFinalize::visitMemoryInit(MemoryInit* curr) { curr->finalize(); }
void ReFinalize::visitDataDrop(DataDrop* curr) { curr->finalize(); }
void ReFinalize::visitMemoryCopy(MemoryCopy* curr) { curr->finalize(); }
diff --git a/src/ir/effects.h b/src/ir/effects.h
index dc6c10645..1a713f944 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -385,6 +385,16 @@ struct EffectAnalyzer
implicitTrap = true;
}
}
+ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ if (curr->isLoad()) {
+ readsMemory = true;
+ } else {
+ writesMemory = true;
+ }
+ if (!ignoreImplicitTraps) {
+ implicitTrap = true;
+ }
+ }
void visitMemoryInit(MemoryInit* curr) {
writesMemory = true;
if (!ignoreImplicitTraps) {
diff --git a/src/ir/utils.h b/src/ir/utils.h
index c2d7645f7..cd50aa1cc 100644
--- a/src/ir/utils.h
+++ b/src/ir/utils.h
@@ -135,6 +135,7 @@ struct ReFinalize
void visitSIMDTernary(SIMDTernary* curr);
void visitSIMDShift(SIMDShift* curr);
void visitSIMDLoad(SIMDLoad* curr);
+ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr);
void visitMemoryInit(MemoryInit* curr);
void visitDataDrop(DataDrop* curr);
void visitMemoryCopy(MemoryCopy* curr);
@@ -219,6 +220,7 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> {
void visitSIMDTernary(SIMDTernary* curr) { curr->finalize(); }
void visitSIMDShift(SIMDShift* curr) { curr->finalize(); }
void visitSIMDLoad(SIMDLoad* curr) { curr->finalize(); }
+ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { curr->finalize(); }
void visitMemoryInit(MemoryInit* curr) { curr->finalize(); }
void visitDataDrop(DataDrop* curr) { curr->finalize(); }
void visitMemoryCopy(MemoryCopy* curr) { curr->finalize(); }
diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp
index 067bc81e1..a17abfd90 100644
--- a/src/passes/DeadCodeElimination.cpp
+++ b/src/passes/DeadCodeElimination.cpp
@@ -345,6 +345,8 @@ struct DeadCodeElimination
DELEGATE(SIMDShift);
case Expression::Id::SIMDLoadId:
DELEGATE(SIMDLoad);
+ case Expression::Id::SIMDLoadStoreLaneId:
+ DELEGATE(SIMDLoadStoreLane);
case Expression::Id::MemoryInitId:
DELEGATE(MemoryInit);
case Expression::Id::DataDropId:
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index a8e5b0f9c..42dccb4bf 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -499,6 +499,43 @@ struct PrintExpressionContents
o << " align=" << curr->align;
}
}
+ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ prepareColor(o);
+ switch (curr->op) {
+ case LoadLaneVec8x16:
+ o << "v128.load8_lane";
+ break;
+ case LoadLaneVec16x8:
+ o << "v128.load16_lane";
+ break;
+ case LoadLaneVec32x4:
+ o << "v128.load32_lane";
+ break;
+ case LoadLaneVec64x2:
+ o << "v128.load64_lane";
+ break;
+ case StoreLaneVec8x16:
+ o << "v128.store8_lane";
+ break;
+ case StoreLaneVec16x8:
+ o << "v128.store16_lane";
+ break;
+ case StoreLaneVec32x4:
+ o << "v128.store32_lane";
+ break;
+ case StoreLaneVec64x2:
+ o << "v128.store64_lane";
+ break;
+ }
+ restoreNormalColor(o);
+ if (curr->offset) {
+ o << " offset=" << curr->offset;
+ }
+ if (curr->align != curr->getMemBytes()) {
+ o << " align=" << curr->align;
+ }
+ o << " " << int(curr->index);
+ }
void visitMemoryInit(MemoryInit* curr) {
prepareColor(o);
o << "memory.init " << curr->segment;
@@ -1908,6 +1945,14 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> {
printFullLine(curr->ptr);
decIndent();
}
+ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ o << '(';
+ PrintExpressionContents(currFunction, o).visit(curr);
+ incIndent();
+ printFullLine(curr->ptr);
+ printFullLine(curr->vec);
+ decIndent();
+ }
void visitMemoryInit(MemoryInit* curr) {
o << '(';
PrintExpressionContents(currFunction, o).visit(curr);
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index 36cf1fb42..d735e48c9 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -2465,6 +2465,7 @@ private:
if (type != Type::v128) {
return makeSIMDExtract(type);
}
+ // TODO: Add SIMDLoadStoreLane once it is generally available
switch (upTo(7)) {
case 0:
return makeUnary(Type::v128);
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 8c502d6b7..1faf30716 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -791,6 +791,15 @@ enum ASTNodes {
V128Xor = 0x51,
V128Bitselect = 0x52,
+ V128Load8Lane = 0x58,
+ V128Load16Lane = 0x59,
+ V128Load32Lane = 0x5a,
+ V128Load64Lane = 0x5b,
+ V128Store8Lane = 0x5c,
+ V128Store16Lane = 0x5d,
+ V128Store32Lane = 0x5e,
+ V128Store64Lane = 0x5f,
+
I8x16Abs = 0x60,
I8x16Neg = 0x61,
I8x16AnyTrue = 0x62,
@@ -1486,6 +1495,7 @@ public:
bool maybeVisitSIMDTernary(Expression*& out, uint32_t code);
bool maybeVisitSIMDShift(Expression*& out, uint32_t code);
bool maybeVisitSIMDLoad(Expression*& out, uint32_t code);
+ bool maybeVisitSIMDLoadStoreLane(Expression*& out, uint32_t code);
bool maybeVisitMemoryInit(Expression*& out, uint32_t code);
bool maybeVisitDataDrop(Expression*& out, uint32_t code);
bool maybeVisitMemoryCopy(Expression*& out, uint32_t code);
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index 97877a0a1..77e2692f6 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -434,6 +434,22 @@ public:
ret->finalize();
return ret;
}
+ SIMDLoadStoreLane* makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp op,
+ Address offset,
+ Address align,
+ uint8_t index,
+ Expression* ptr,
+ Expression* vec) {
+ auto* ret = wasm.allocator.alloc<SIMDLoadStoreLane>();
+ ret->op = op;
+ ret->offset = offset;
+ ret->align = align;
+ ret->index = index;
+ ret->ptr = ptr;
+ ret->vec = vec;
+ ret->finalize();
+ return ret;
+ }
MemoryInit* makeMemoryInit(uint32_t segment,
Expression* dest,
Expression* offset,
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 203786e72..5ca590208 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1240,6 +1240,9 @@ public:
Flow visitSIMDLoadSplat(SIMDLoad* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitSIMDLoadExtend(SIMDLoad* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitSIMDLoadZero(SIMDLoad* curr) { WASM_UNREACHABLE("unimp"); }
+ Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ WASM_UNREACHABLE("unimp");
+ }
Flow visitPop(Pop* curr) { WASM_UNREACHABLE("unimp"); }
Flow visitRefNull(RefNull* curr) {
NOTE_ENTER("RefNull");
@@ -1627,6 +1630,10 @@ public:
NOTE_ENTER("SIMDLoadExtend");
return Flow(NONCONSTANT_FLOW);
}
+ Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ NOTE_ENTER("SIMDLoadStoreLane");
+ return Flow(NONCONSTANT_FLOW);
+ }
Flow visitPop(Pop* curr) {
NOTE_ENTER("Pop");
return Flow(NONCONSTANT_FLOW);
@@ -2369,7 +2376,7 @@ private:
}
NOTE_EVAL1(flow);
Address src = instance.getFinalAddress(
- curr, flow.getSingleValue(), curr->op == Load32Zero ? 32 : 64);
+ curr, flow.getSingleValue(), curr->getMemBytes());
auto zero =
Literal::makeZero(curr->op == Load32Zero ? Type::i32 : Type::i64);
if (curr->op == Load32Zero) {
@@ -2380,6 +2387,76 @@ private:
return Literal(std::array<Literal, 2>{{val, zero}});
}
}
+ Flow visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ NOTE_ENTER("SIMDLoadStoreLane");
+ Flow flow = this->visit(curr->ptr);
+ if (flow.breaking()) {
+ return flow;
+ }
+ NOTE_EVAL1(flow);
+ Address addr = instance.getFinalAddress(
+ curr, flow.getSingleValue(), curr->getMemBytes());
+ flow = this->visit(curr->vec);
+ if (flow.breaking()) {
+ return flow;
+ }
+ Literal vec = flow.getSingleValue();
+ switch (curr->op) {
+ case LoadLaneVec8x16:
+ case StoreLaneVec8x16: {
+ std::array<Literal, 16> lanes = vec.getLanesUI8x16();
+ if (curr->isLoad()) {
+ lanes[curr->index] =
+ Literal(instance.externalInterface->load8u(addr));
+ return Literal(lanes);
+ } else {
+ instance.externalInterface->store8(addr,
+ lanes[curr->index].geti32());
+ return {};
+ }
+ }
+ case LoadLaneVec16x8:
+ case StoreLaneVec16x8: {
+ std::array<Literal, 8> lanes = vec.getLanesUI16x8();
+ if (curr->isLoad()) {
+ lanes[curr->index] =
+ Literal(instance.externalInterface->load16u(addr));
+ return Literal(lanes);
+ } else {
+ instance.externalInterface->store16(addr,
+ lanes[curr->index].geti32());
+ return {};
+ }
+ }
+ case LoadLaneVec32x4:
+ case StoreLaneVec32x4: {
+ std::array<Literal, 4> lanes = vec.getLanesI32x4();
+ if (curr->isLoad()) {
+ lanes[curr->index] =
+ Literal(instance.externalInterface->load32u(addr));
+ return Literal(lanes);
+ } else {
+ instance.externalInterface->store32(addr,
+ lanes[curr->index].geti32());
+ return {};
+ }
+ }
+ case StoreLaneVec64x2:
+ case LoadLaneVec64x2: {
+ std::array<Literal, 2> lanes = vec.getLanesI64x2();
+ if (curr->isLoad()) {
+ lanes[curr->index] =
+ Literal(instance.externalInterface->load64u(addr));
+ return Literal(lanes);
+ } else {
+ instance.externalInterface->store64(addr,
+ lanes[curr->index].geti64());
+ return {};
+ }
+ }
+ }
+ WASM_UNREACHABLE("unexpected op");
+ }
Flow visitMemorySize(MemorySize* curr) {
NOTE_ENTER("MemorySize");
return Literal::makeFromInt64(instance.memorySize,
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index b6dcc058c..ac1b6d0e5 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -212,6 +212,7 @@ private:
Expression* makeSIMDTernary(Element& s, SIMDTernaryOp op);
Expression* makeSIMDShift(Element& s, SIMDShiftOp op);
Expression* makeSIMDLoad(Element& s, SIMDLoadOp op);
+ Expression* makeSIMDLoadStoreLane(Element& s, SIMDLoadStoreLaneOp op);
Expression* makeMemoryInit(Element& s);
Expression* makeDataDrop(Element& s);
Expression* makeMemoryCopy(Element& s);
diff --git a/src/wasm-stack.h b/src/wasm-stack.h
index d4d04f850..951e06daa 100644
--- a/src/wasm-stack.h
+++ b/src/wasm-stack.h
@@ -123,6 +123,7 @@ public:
void visitSIMDTernary(SIMDTernary* curr);
void visitSIMDShift(SIMDShift* curr);
void visitSIMDLoad(SIMDLoad* curr);
+ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr);
void visitMemoryInit(MemoryInit* curr);
void visitDataDrop(DataDrop* curr);
void visitMemoryCopy(MemoryCopy* curr);
diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h
index b32babf74..25988598a 100644
--- a/src/wasm-traversal.h
+++ b/src/wasm-traversal.h
@@ -61,6 +61,9 @@ template<typename SubType, typename ReturnType = void> struct Visitor {
ReturnType visitSIMDTernary(SIMDTernary* curr) { return ReturnType(); }
ReturnType visitSIMDShift(SIMDShift* curr) { return ReturnType(); }
ReturnType visitSIMDLoad(SIMDLoad* curr) { return ReturnType(); }
+ ReturnType visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ return ReturnType();
+ }
ReturnType visitMemoryInit(MemoryInit* curr) { return ReturnType(); }
ReturnType visitDataDrop(DataDrop* curr) { return ReturnType(); }
ReturnType visitMemoryCopy(MemoryCopy* curr) { return ReturnType(); }
@@ -290,6 +293,7 @@ struct OverriddenVisitor {
UNIMPLEMENTED(SIMDTernary);
UNIMPLEMENTED(SIMDShift);
UNIMPLEMENTED(SIMDLoad);
+ UNIMPLEMENTED(SIMDLoadStoreLane);
UNIMPLEMENTED(MemoryInit);
UNIMPLEMENTED(DataDrop);
UNIMPLEMENTED(MemoryCopy);
@@ -395,6 +399,8 @@ struct OverriddenVisitor {
DELEGATE(SIMDShift);
case Expression::Id::SIMDLoadId:
DELEGATE(SIMDLoad);
+ case Expression::Id::SIMDLoadStoreLaneId:
+ DELEGATE(SIMDLoadStoreLane);
case Expression::Id::MemoryInitId:
DELEGATE(MemoryInit);
case Expression::Id::DataDropId:
@@ -925,6 +931,9 @@ struct Walker : public VisitorType {
static void doVisitSIMDLoad(SubType* self, Expression** currp) {
self->visitSIMDLoad((*currp)->cast<SIMDLoad>());
}
+ static void doVisitSIMDLoadStoreLane(SubType* self, Expression** currp) {
+ self->visitSIMDLoadStoreLane((*currp)->cast<SIMDLoadStoreLane>());
+ }
static void doVisitMemoryInit(SubType* self, Expression** currp) {
self->visitMemoryInit((*currp)->cast<MemoryInit>());
}
@@ -1211,6 +1220,12 @@ struct PostWalker : public Walker<SubType, VisitorType> {
self->pushTask(SubType::scan, &curr->cast<SIMDLoad>()->ptr);
break;
}
+ case Expression::Id::SIMDLoadStoreLaneId: {
+ self->pushTask(SubType::doVisitSIMDLoadStoreLane, currp);
+ self->pushTask(SubType::scan, &curr->cast<SIMDLoadStoreLane>()->vec);
+ self->pushTask(SubType::scan, &curr->cast<SIMDLoadStoreLane>()->ptr);
+ break;
+ }
case Expression::Id::MemoryInitId: {
self->pushTask(SubType::doVisitMemoryInit, currp);
self->pushTask(SubType::scan, &curr->cast<MemoryInit>()->size);
diff --git a/src/wasm.h b/src/wasm.h
index 40859eefc..e2b97204b 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -481,7 +481,18 @@ enum SIMDLoadOp {
LoadExtSVec32x2ToVecI64x2,
LoadExtUVec32x2ToVecI64x2,
Load32Zero,
- Load64Zero
+ Load64Zero,
+};
+
+enum SIMDLoadStoreLaneOp {
+ LoadLaneVec8x16,
+ LoadLaneVec16x8,
+ LoadLaneVec32x4,
+ LoadLaneVec64x2,
+ StoreLaneVec8x16,
+ StoreLaneVec16x8,
+ StoreLaneVec32x4,
+ StoreLaneVec64x2,
};
enum SIMDTernaryOp { Bitselect, QFMAF32x4, QFMSF32x4, QFMAF64x2, QFMSF64x2 };
@@ -545,6 +556,7 @@ public:
SIMDTernaryId,
SIMDShiftId,
SIMDLoadId,
+ SIMDLoadStoreLaneId,
MemoryInitId,
DataDropId,
MemoryCopyId,
@@ -970,6 +982,25 @@ public:
void finalize();
};
+class SIMDLoadStoreLane
+ : public SpecificExpression<Expression::SIMDLoadStoreLaneId> {
+public:
+ SIMDLoadStoreLane() = default;
+ SIMDLoadStoreLane(MixedArena& allocator) {}
+
+ SIMDLoadStoreLaneOp op;
+ Address offset;
+ Address align;
+ uint8_t index;
+ Expression* ptr;
+ Expression* vec;
+
+ bool isStore();
+ bool isLoad() { return !isStore(); }
+ Index getMemBytes();
+ void finalize();
+};
+
class MemoryInit : public SpecificExpression<Expression::MemoryInitId> {
public:
MemoryInit() = default;
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b6e926f6a..80f82dd5e 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -2711,6 +2711,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitSIMDLoad(curr, opcode)) {
break;
}
+ if (maybeVisitSIMDLoadStoreLane(curr, opcode)) {
+ break;
+ }
throwError("invalid code after SIMD prefix: " + std::to_string(opcode));
break;
}
@@ -4980,6 +4983,57 @@ bool WasmBinaryBuilder::maybeVisitSIMDLoad(Expression*& out, uint32_t code) {
return true;
}
+bool WasmBinaryBuilder::maybeVisitSIMDLoadStoreLane(Expression*& out,
+ uint32_t code) {
+ SIMDLoadStoreLaneOp op;
+ size_t lanes;
+ switch (code) {
+ case BinaryConsts::V128Load8Lane:
+ op = LoadLaneVec8x16;
+ lanes = 16;
+ break;
+ case BinaryConsts::V128Load16Lane:
+ op = LoadLaneVec16x8;
+ lanes = 8;
+ break;
+ case BinaryConsts::V128Load32Lane:
+ op = LoadLaneVec32x4;
+ lanes = 4;
+ break;
+ case BinaryConsts::V128Load64Lane:
+ op = LoadLaneVec64x2;
+ lanes = 2;
+ break;
+ case BinaryConsts::V128Store8Lane:
+ op = StoreLaneVec8x16;
+ lanes = 16;
+ break;
+ case BinaryConsts::V128Store16Lane:
+ op = StoreLaneVec16x8;
+ lanes = 8;
+ break;
+ case BinaryConsts::V128Store32Lane:
+ op = StoreLaneVec32x4;
+ lanes = 4;
+ break;
+ case BinaryConsts::V128Store64Lane:
+ op = StoreLaneVec64x2;
+ lanes = 2;
+ break;
+ default:
+ return false;
+ }
+ auto* curr = allocator.alloc<SIMDLoadStoreLane>();
+ curr->op = op;
+ readMemoryAccess(curr->align, curr->offset);
+ curr->index = getLaneIndex(lanes);
+ curr->vec = popNonVoidExpression();
+ curr->ptr = popNonVoidExpression();
+ curr->finalize();
+ out = curr;
+ return true;
+}
+
void WasmBinaryBuilder::visitSelect(Select* curr, uint8_t code) {
BYN_TRACE("zz node: Select, code " << int32_t(code) << std::endl);
if (code == BinaryConsts::SelectWithType) {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index c4de76987..4e06a75bb 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1300,8 +1300,12 @@ static size_t parseMemAttributes(Element& s,
size_t i = 1;
offset = 0;
align = fallbackAlign;
+ // Parse "align=X" and "offset=X" arguments, bailing out on anything else.
while (!s[i]->isList()) {
const char* str = s[i]->c_str();
+ if (strncmp(str, "align", 5) != 0 && strncmp(str, "offset", 6) != 0) {
+ return i;
+ }
const char* eq = strchr(str, '=');
if (!eq) {
throw ParseException(
@@ -1592,6 +1596,45 @@ Expression* SExpressionWasmBuilder::makeSIMDLoad(Element& s, SIMDLoadOp op) {
return ret;
}
+Expression*
+SExpressionWasmBuilder::makeSIMDLoadStoreLane(Element& s,
+ SIMDLoadStoreLaneOp op) {
+ auto* ret = allocator.alloc<SIMDLoadStoreLane>();
+ ret->op = op;
+ Address defaultAlign;
+ size_t lanes;
+ switch (op) {
+ case LoadLaneVec8x16:
+ case StoreLaneVec8x16:
+ defaultAlign = 1;
+ lanes = 16;
+ break;
+ case LoadLaneVec16x8:
+ case StoreLaneVec16x8:
+ defaultAlign = 2;
+ lanes = 8;
+ break;
+ case LoadLaneVec32x4:
+ case StoreLaneVec32x4:
+ defaultAlign = 4;
+ lanes = 4;
+ break;
+ case LoadLaneVec64x2:
+ case StoreLaneVec64x2:
+ defaultAlign = 8;
+ lanes = 2;
+ break;
+ default:
+ WASM_UNREACHABLE("Unexpected SIMDLoadStoreLane op");
+ }
+ size_t i = parseMemAttributes(s, ret->offset, ret->align, defaultAlign);
+ ret->index = parseLaneIndex(s[i++], lanes);
+ ret->ptr = parseExpression(s[i++]);
+ ret->vec = parseExpression(s[i]);
+ ret->finalize();
+ return ret;
+}
+
Expression* SExpressionWasmBuilder::makeMemoryInit(Element& s) {
auto ret = allocator.alloc<MemoryInit>();
ret->segment = atoi(s[1]->str().c_str());
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index fcf9e4b8a..4bc479d15 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -647,6 +647,39 @@ void BinaryInstWriter::visitSIMDLoad(SIMDLoad* curr) {
emitMemoryAccess(curr->align, /*(unused) bytes=*/0, curr->offset);
}
+void BinaryInstWriter::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ o << int8_t(BinaryConsts::SIMDPrefix);
+ switch (curr->op) {
+ case LoadLaneVec8x16:
+ o << U32LEB(BinaryConsts::V128Load8Lane);
+ break;
+ case LoadLaneVec16x8:
+ o << U32LEB(BinaryConsts::V128Load16Lane);
+ break;
+ case LoadLaneVec32x4:
+ o << U32LEB(BinaryConsts::V128Load32Lane);
+ break;
+ case LoadLaneVec64x2:
+ o << U32LEB(BinaryConsts::V128Load64Lane);
+ break;
+ case StoreLaneVec8x16:
+ o << U32LEB(BinaryConsts::V128Store8Lane);
+ break;
+ case StoreLaneVec16x8:
+ o << U32LEB(BinaryConsts::V128Store16Lane);
+ break;
+ case StoreLaneVec32x4:
+ o << U32LEB(BinaryConsts::V128Store32Lane);
+ break;
+ case StoreLaneVec64x2:
+ o << U32LEB(BinaryConsts::V128Store64Lane);
+ break;
+ }
+ assert(curr->align);
+ emitMemoryAccess(curr->align, /*(unused) bytes=*/0, curr->offset);
+ o << curr->index;
+}
+
void BinaryInstWriter::visitMemoryInit(MemoryInit* curr) {
o << int8_t(BinaryConsts::MiscPrefix);
o << U32LEB(BinaryConsts::MemoryInit);
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index ef6a29373..31b68a80c 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -317,6 +317,7 @@ public:
void visitSIMDTernary(SIMDTernary* curr);
void visitSIMDShift(SIMDShift* curr);
void visitSIMDLoad(SIMDLoad* curr);
+ void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr);
void visitMemoryInit(MemoryInit* curr);
void visitDataDrop(DataDrop* curr);
void visitMemoryCopy(MemoryCopy* curr);
@@ -1264,6 +1265,59 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
validateAlignment(curr->align, memAlignType, bytes, /*isAtomic=*/false, curr);
}
+void FunctionValidator::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ shouldBeTrue(
+ getModule()->memory.exists, curr, "Memory operations require a memory");
+ shouldBeTrue(
+ getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)");
+ if (curr->isLoad()) {
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->type, Type(Type::v128), curr, "loadX_lane must have type v128");
+ } else {
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->type, Type(Type::none), curr, "storeX_lane must have type none");
+ }
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "loadX_lane or storeX_lane address must match memory index type");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->vec->type,
+ Type(Type::v128),
+ curr,
+ "loadX_lane or storeX_lane vector argument must have type v128");
+ size_t lanes;
+ Type memAlignType = Type::none;
+ switch (curr->op) {
+ case LoadLaneVec8x16:
+ case StoreLaneVec8x16:
+ lanes = 16;
+ memAlignType = Type::i32;
+ break;
+ case LoadLaneVec16x8:
+ case StoreLaneVec16x8:
+ lanes = 8;
+ memAlignType = Type::i32;
+ break;
+ case LoadLaneVec32x4:
+ case StoreLaneVec32x4:
+ lanes = 4;
+ memAlignType = Type::i32;
+ break;
+ case LoadLaneVec64x2:
+ case StoreLaneVec64x2:
+ lanes = 2;
+ memAlignType = Type::i64;
+ break;
+ default:
+ WASM_UNREACHABLE("Unexpected SIMDLoadStoreLane op");
+ }
+ Index bytes = curr->getMemBytes();
+ validateAlignment(curr->align, memAlignType, bytes, /*isAtomic=*/false, curr);
+ shouldBeTrue(curr->index < lanes, curr, "invalid lane index");
+}
+
void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
shouldBeTrue(getModule()->features.hasBulkMemory(),
curr,
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 2052afa89..472902ad5 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -175,6 +175,8 @@ const char* getExpressionName(Expression* curr) {
return "simd_shift";
case Expression::Id::SIMDLoadId:
return "simd_load";
+ case Expression::Id::SIMDLoadStoreLaneId:
+ return "simd_load_store_lane";
case Expression::Id::MemoryInitId:
return "memory_init";
case Expression::Id::DataDropId:
@@ -674,6 +676,48 @@ Index SIMDLoad::getMemBytes() {
WASM_UNREACHABLE("unexpected op");
}
+void SIMDLoadStoreLane::finalize() {
+ assert(ptr && vec);
+ type = isLoad() ? Type::v128 : Type::none;
+ if (ptr->type == Type::unreachable || vec->type == Type::unreachable) {
+ type = Type::unreachable;
+ }
+}
+
+Index SIMDLoadStoreLane::getMemBytes() {
+ switch (op) {
+ case LoadLaneVec8x16:
+ case StoreLaneVec8x16:
+ return 1;
+ case LoadLaneVec16x8:
+ case StoreLaneVec16x8:
+ return 2;
+ case LoadLaneVec32x4:
+ case StoreLaneVec32x4:
+ return 4;
+ case LoadLaneVec64x2:
+ case StoreLaneVec64x2:
+ return 8;
+ }
+ WASM_UNREACHABLE("unexpected op");
+}
+
+bool SIMDLoadStoreLane::isStore() {
+ switch (op) {
+ case StoreLaneVec8x16:
+ case StoreLaneVec16x8:
+ case StoreLaneVec32x4:
+ case StoreLaneVec64x2:
+ return true;
+ case LoadLaneVec16x8:
+ case LoadLaneVec32x4:
+ case LoadLaneVec64x2:
+ case LoadLaneVec8x16:
+ return false;
+ }
+ WASM_UNREACHABLE("unexpected op");
+}
+
Const* Const::set(Literal value_) {
value = value_;
type = value.type;
diff --git a/src/wasm2js.h b/src/wasm2js.h
index c5297a12a..8d7e9d105 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -2070,6 +2070,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
unimplemented(curr);
WASM_UNREACHABLE("unimp");
}
+ Ref visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
+ unimplemented(curr);
+ WASM_UNREACHABLE("unimp");
+ }
Ref visitMemoryInit(MemoryInit* curr) {
ABI::wasm2js::ensureHelpers(module, ABI::wasm2js::MEMORY_INIT);
return ValueBuilder::makeCall(ABI::wasm2js::MEMORY_INIT,
diff --git a/test/binaryen.js/exception-handling.js.txt b/test/binaryen.js/exception-handling.js.txt
index a586691d3..5728fa9ab 100644
--- a/test/binaryen.js/exception-handling.js.txt
+++ b/test/binaryen.js/exception-handling.js.txt
@@ -28,7 +28,7 @@
)
)
-getExpressionInfo(throw) = {"id":45,"type":1,"event":"e"}
-getExpressionInfo(br_on_exn) = {"id":47,"type":9,"name":"l","event":"e"}
-getExpressionInfo(rethrow) = {"id":46,"type":1}
-getExpressionInfo(try) = {"id":44,"type":0}
+getExpressionInfo(throw) = {"id":46,"type":1,"event":"e"}
+getExpressionInfo(br_on_exn) = {"id":48,"type":9,"name":"l","event":"e"}
+getExpressionInfo(rethrow) = {"id":47,"type":1}
+getExpressionInfo(try) = {"id":45,"type":0}
diff --git a/test/binaryen.js/kitchen-sink.js.txt b/test/binaryen.js/kitchen-sink.js.txt
index db3ee1605..6c32962a7 100644
--- a/test/binaryen.js/kitchen-sink.js.txt
+++ b/test/binaryen.js/kitchen-sink.js.txt
@@ -76,35 +76,35 @@ SIMDShuffleId: 31
SIMDTernaryId: 32
SIMDShiftId: 33
SIMDLoadId: 34
-MemoryInitId: 35
-DataDropId: 36
-MemoryCopyId: 37
-MemoryFillId: 38
-PopId: 39
-RefNullId: 40
-RefIsNullId: 41
-RefFuncId: 42
-RefEqId: 43
-TryId: 44
-ThrowId: 45
-RethrowId: 46
-BrOnExnId: 47
-TupleMakeId: 48
-TupleExtractId: 49
-I31NewId: 50
-I31GetId: 51
-RefTestId: 52
-RefCastId: 53
-BrOnCastId: 54
-RttCanonId: 55
-RttSubId: 56
-StructNewId: 57
-StructGetId: 58
-StructSetId: 59
-ArrayNewId: 60
-ArrayGetId: 61
-ArraySetId: 62
-ArrayLenId: 63
+MemoryInitId: 36
+DataDropId: 37
+MemoryCopyId: 38
+MemoryFillId: 39
+PopId: 40
+RefNullId: 41
+RefIsNullId: 42
+RefFuncId: 43
+RefEqId: 44
+TryId: 45
+ThrowId: 46
+RethrowId: 47
+BrOnExnId: 48
+TupleMakeId: 49
+TupleExtractId: 50
+I31NewId: 51
+I31GetId: 52
+RefTestId: 53
+RefCastId: 54
+BrOnCastId: 55
+RttCanonId: 56
+RttSubId: 57
+StructNewId: 58
+StructGetId: 59
+StructSetId: 60
+ArrayNewId: 61
+ArrayGetId: 62
+ArraySetId: 63
+ArrayLenId: 64
getExpressionInfo={"id":15,"type":4,"op":6}
(f32.neg
(f32.const -33.61199951171875)
diff --git a/test/simd.wast b/test/simd.wast
index 619d1a577..6bca3f1b4 100644
--- a/test/simd.wast
+++ b/test/simd.wast
@@ -424,6 +424,90 @@
(local.get $2)
)
)
+ (func $v128.load8_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load8_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load16_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load16_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load32_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load32_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_align (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_offset (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_align_offset (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane align=1 offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store8_lane (param $0 i32) (param $1 v128)
+ (v128.store8_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store16_lane (param $0 i32) (param $1 v128)
+ (v128.store16_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store32_lane (param $0 i32) (param $1 v128)
+ (v128.store32_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane (param $0 i32) (param $1 v128)
+ (v128.store64_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_align (param $0 i32) (param $1 v128)
+ (v128.store64_lane align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_offset (param $0 i32) (param $1 v128)
+ (v128.store64_lane offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_align_offset (param $0 i32) (param $1 v128)
+ (v128.store64_lane align=1 offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
(func $i8x16.abs (param $0 v128) (result v128)
(i8x16.abs
(local.get $0)
diff --git a/test/simd.wast.from-wast b/test/simd.wast.from-wast
index af57494e3..e402bab08 100644
--- a/test/simd.wast.from-wast
+++ b/test/simd.wast.from-wast
@@ -4,9 +4,10 @@
(type $v128_=>_i32 (func (param v128) (result i32)))
(type $i32_=>_v128 (func (param i32) (result v128)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
+ (type $i32_v128_=>_none (func (param i32 v128)))
+ (type $i32_v128_=>_v128 (func (param i32 v128) (result v128)))
(type $none_=>_v128 (func (result v128)))
(type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128)))
- (type $i32_v128_=>_none (func (param i32 v128)))
(type $v128_=>_i64 (func (param v128) (result i64)))
(type $v128_=>_f32 (func (param v128) (result f32)))
(type $v128_=>_f64 (func (param v128) (result f64)))
@@ -440,6 +441,90 @@
(local.get $2)
)
)
+ (func $v128.load8_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load8_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load16_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load16_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load32_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load32_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_align (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_offset (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_align_offset (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane offset=32 align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store8_lane (param $0 i32) (param $1 v128)
+ (v128.store8_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store16_lane (param $0 i32) (param $1 v128)
+ (v128.store16_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store32_lane (param $0 i32) (param $1 v128)
+ (v128.store32_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane (param $0 i32) (param $1 v128)
+ (v128.store64_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_align (param $0 i32) (param $1 v128)
+ (v128.store64_lane align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_offset (param $0 i32) (param $1 v128)
+ (v128.store64_lane offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_align_offset (param $0 i32) (param $1 v128)
+ (v128.store64_lane offset=32 align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
(func $i8x16.abs (param $0 v128) (result v128)
(i8x16.abs
(local.get $0)
diff --git a/test/simd.wast.fromBinary b/test/simd.wast.fromBinary
index a56689449..932b45950 100644
--- a/test/simd.wast.fromBinary
+++ b/test/simd.wast.fromBinary
@@ -4,9 +4,10 @@
(type $v128_=>_i32 (func (param v128) (result i32)))
(type $i32_=>_v128 (func (param i32) (result v128)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
+ (type $i32_v128_=>_none (func (param i32 v128)))
+ (type $i32_v128_=>_v128 (func (param i32 v128) (result v128)))
(type $none_=>_v128 (func (result v128)))
(type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128)))
- (type $i32_v128_=>_none (func (param i32 v128)))
(type $v128_=>_i64 (func (param v128) (result i64)))
(type $v128_=>_f32 (func (param v128) (result f32)))
(type $v128_=>_f64 (func (param v128) (result f64)))
@@ -440,6 +441,90 @@
(local.get $2)
)
)
+ (func $v128.load8_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load8_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load16_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load16_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load32_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load32_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_align (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_offset (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.load64_lane_align_offset (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane offset=32 align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store8_lane (param $0 i32) (param $1 v128)
+ (v128.store8_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store16_lane (param $0 i32) (param $1 v128)
+ (v128.store16_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store32_lane (param $0 i32) (param $1 v128)
+ (v128.store32_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane (param $0 i32) (param $1 v128)
+ (v128.store64_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_align (param $0 i32) (param $1 v128)
+ (v128.store64_lane align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_offset (param $0 i32) (param $1 v128)
+ (v128.store64_lane offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $v128.store64_lane_align_offset (param $0 i32) (param $1 v128)
+ (v128.store64_lane offset=32 align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
(func $i8x16.abs (param $0 v128) (result v128)
(i8x16.abs
(local.get $0)
diff --git a/test/simd.wast.fromBinary.noDebugInfo b/test/simd.wast.fromBinary.noDebugInfo
index c3bfb8a54..71bf02e56 100644
--- a/test/simd.wast.fromBinary.noDebugInfo
+++ b/test/simd.wast.fromBinary.noDebugInfo
@@ -4,9 +4,10 @@
(type $v128_=>_i32 (func (param v128) (result i32)))
(type $i32_=>_v128 (func (param i32) (result v128)))
(type $v128_i32_=>_v128 (func (param v128 i32) (result v128)))
+ (type $i32_v128_=>_none (func (param i32 v128)))
+ (type $i32_v128_=>_v128 (func (param i32 v128) (result v128)))
(type $none_=>_v128 (func (result v128)))
(type $v128_v128_v128_=>_v128 (func (param v128 v128 v128) (result v128)))
- (type $i32_v128_=>_none (func (param i32 v128)))
(type $v128_=>_i64 (func (param v128) (result i64)))
(type $v128_=>_f32 (func (param v128) (result f32)))
(type $v128_=>_f64 (func (param v128) (result f64)))
@@ -440,737 +441,821 @@
(local.get $2)
)
)
- (func $76 (param $0 v128) (result v128)
+ (func $76 (param $0 i32) (param $1 v128) (result v128)
+ (v128.load8_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $77 (param $0 i32) (param $1 v128) (result v128)
+ (v128.load16_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $78 (param $0 i32) (param $1 v128) (result v128)
+ (v128.load32_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $79 (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $80 (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $81 (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $82 (param $0 i32) (param $1 v128) (result v128)
+ (v128.load64_lane offset=32 align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $83 (param $0 i32) (param $1 v128)
+ (v128.store8_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $84 (param $0 i32) (param $1 v128)
+ (v128.store16_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $85 (param $0 i32) (param $1 v128)
+ (v128.store32_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $86 (param $0 i32) (param $1 v128)
+ (v128.store64_lane 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $87 (param $0 i32) (param $1 v128)
+ (v128.store64_lane align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $88 (param $0 i32) (param $1 v128)
+ (v128.store64_lane offset=32 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $89 (param $0 i32) (param $1 v128)
+ (v128.store64_lane offset=32 align=1 0
+ (local.get $0)
+ (local.get $1)
+ )
+ )
+ (func $90 (param $0 v128) (result v128)
(i8x16.abs
(local.get $0)
)
)
- (func $77 (param $0 v128) (result v128)
+ (func $91 (param $0 v128) (result v128)
(i8x16.neg
(local.get $0)
)
)
- (func $78 (param $0 v128) (result i32)
+ (func $92 (param $0 v128) (result i32)
(i8x16.any_true
(local.get $0)
)
)
- (func $79 (param $0 v128) (result i32)
+ (func $93 (param $0 v128) (result i32)
(i8x16.all_true
(local.get $0)
)
)
- (func $80 (param $0 v128) (result i32)
+ (func $94 (param $0 v128) (result i32)
(i8x16.bitmask
(local.get $0)
)
)
- (func $81 (param $0 v128) (param $1 i32) (result v128)
+ (func $95 (param $0 v128) (param $1 i32) (result v128)
(i8x16.shl
(local.get $0)
(local.get $1)
)
)
- (func $82 (param $0 v128) (param $1 i32) (result v128)
+ (func $96 (param $0 v128) (param $1 i32) (result v128)
(i8x16.shr_s
(local.get $0)
(local.get $1)
)
)
- (func $83 (param $0 v128) (param $1 i32) (result v128)
+ (func $97 (param $0 v128) (param $1 i32) (result v128)
(i8x16.shr_u
(local.get $0)
(local.get $1)
)
)
- (func $84 (param $0 v128) (param $1 v128) (result v128)
+ (func $98 (param $0 v128) (param $1 v128) (result v128)
(i8x16.add
(local.get $0)
(local.get $1)
)
)
- (func $85 (param $0 v128) (param $1 v128) (result v128)
+ (func $99 (param $0 v128) (param $1 v128) (result v128)
(i8x16.add_saturate_s
(local.get $0)
(local.get $1)
)
)
- (func $86 (param $0 v128) (param $1 v128) (result v128)
+ (func $100 (param $0 v128) (param $1 v128) (result v128)
(i8x16.add_saturate_u
(local.get $0)
(local.get $1)
)
)
- (func $87 (param $0 v128) (param $1 v128) (result v128)
+ (func $101 (param $0 v128) (param $1 v128) (result v128)
(i8x16.sub
(local.get $0)
(local.get $1)
)
)
- (func $88 (param $0 v128) (param $1 v128) (result v128)
+ (func $102 (param $0 v128) (param $1 v128) (result v128)
(i8x16.sub_saturate_s
(local.get $0)
(local.get $1)
)
)
- (func $89 (param $0 v128) (param $1 v128) (result v128)
+ (func $103 (param $0 v128) (param $1 v128) (result v128)
(i8x16.sub_saturate_u
(local.get $0)
(local.get $1)
)
)
- (func $90 (param $0 v128) (param $1 v128) (result v128)
+ (func $104 (param $0 v128) (param $1 v128) (result v128)
(i8x16.mul
(local.get $0)
(local.get $1)
)
)
- (func $91 (param $0 v128) (param $1 v128) (result v128)
+ (func $105 (param $0 v128) (param $1 v128) (result v128)
(i8x16.min_s
(local.get $0)
(local.get $1)
)
)
- (func $92 (param $0 v128) (param $1 v128) (result v128)
+ (func $106 (param $0 v128) (param $1 v128) (result v128)
(i8x16.min_u
(local.get $0)
(local.get $1)
)
)
- (func $93 (param $0 v128) (param $1 v128) (result v128)
+ (func $107 (param $0 v128) (param $1 v128) (result v128)
(i8x16.max_s
(local.get $0)
(local.get $1)
)
)
- (func $94 (param $0 v128) (param $1 v128) (result v128)
+ (func $108 (param $0 v128) (param $1 v128) (result v128)
(i8x16.max_u
(local.get $0)
(local.get $1)
)
)
- (func $95 (param $0 v128) (param $1 v128) (result v128)
+ (func $109 (param $0 v128) (param $1 v128) (result v128)
(i8x16.avgr_u
(local.get $0)
(local.get $1)
)
)
- (func $96 (param $0 v128) (result v128)
+ (func $110 (param $0 v128) (result v128)
(i16x8.abs
(local.get $0)
)
)
- (func $97 (param $0 v128) (result v128)
+ (func $111 (param $0 v128) (result v128)
(i16x8.neg
(local.get $0)
)
)
- (func $98 (param $0 v128) (result i32)
+ (func $112 (param $0 v128) (result i32)
(i16x8.any_true
(local.get $0)
)
)
- (func $99 (param $0 v128) (result i32)
+ (func $113 (param $0 v128) (result i32)
(i16x8.all_true
(local.get $0)
)
)
- (func $100 (param $0 v128) (result i32)
+ (func $114 (param $0 v128) (result i32)
(i16x8.bitmask
(local.get $0)
)
)
- (func $101 (param $0 v128) (param $1 i32) (result v128)
+ (func $115 (param $0 v128) (param $1 i32) (result v128)
(i16x8.shl
(local.get $0)
(local.get $1)
)
)
- (func $102 (param $0 v128) (param $1 i32) (result v128)
+ (func $116 (param $0 v128) (param $1 i32) (result v128)
(i16x8.shr_s
(local.get $0)
(local.get $1)
)
)
- (func $103 (param $0 v128) (param $1 i32) (result v128)
+ (func $117 (param $0 v128) (param $1 i32) (result v128)
(i16x8.shr_u
(local.get $0)
(local.get $1)
)
)
- (func $104 (param $0 v128) (param $1 v128) (result v128)
+ (func $118 (param $0 v128) (param $1 v128) (result v128)
(i16x8.add
(local.get $0)
(local.get $1)
)
)
- (func $105 (param $0 v128) (param $1 v128) (result v128)
+ (func $119 (param $0 v128) (param $1 v128) (result v128)
(i16x8.add_saturate_s
(local.get $0)
(local.get $1)
)
)
- (func $106 (param $0 v128) (param $1 v128) (result v128)
+ (func $120 (param $0 v128) (param $1 v128) (result v128)
(i16x8.add_saturate_u
(local.get $0)
(local.get $1)
)
)
- (func $107 (param $0 v128) (param $1 v128) (result v128)
+ (func $121 (param $0 v128) (param $1 v128) (result v128)
(i16x8.sub
(local.get $0)
(local.get $1)
)
)
- (func $108 (param $0 v128) (param $1 v128) (result v128)
+ (func $122 (param $0 v128) (param $1 v128) (result v128)
(i16x8.sub_saturate_s
(local.get $0)
(local.get $1)
)
)
- (func $109 (param $0 v128) (param $1 v128) (result v128)
+ (func $123 (param $0 v128) (param $1 v128) (result v128)
(i16x8.sub_saturate_u
(local.get $0)
(local.get $1)
)
)
- (func $110 (param $0 v128) (param $1 v128) (result v128)
+ (func $124 (param $0 v128) (param $1 v128) (result v128)
(i16x8.mul
(local.get $0)
(local.get $1)
)
)
- (func $111 (param $0 v128) (param $1 v128) (result v128)
+ (func $125 (param $0 v128) (param $1 v128) (result v128)
(i16x8.min_s
(local.get $0)
(local.get $1)
)
)
- (func $112 (param $0 v128) (param $1 v128) (result v128)
+ (func $126 (param $0 v128) (param $1 v128) (result v128)
(i16x8.min_u
(local.get $0)
(local.get $1)
)
)
- (func $113 (param $0 v128) (param $1 v128) (result v128)
+ (func $127 (param $0 v128) (param $1 v128) (result v128)
(i16x8.max_s
(local.get $0)
(local.get $1)
)
)
- (func $114 (param $0 v128) (param $1 v128) (result v128)
+ (func $128 (param $0 v128) (param $1 v128) (result v128)
(i16x8.max_u
(local.get $0)
(local.get $1)
)
)
- (func $115 (param $0 v128) (param $1 v128) (result v128)
+ (func $129 (param $0 v128) (param $1 v128) (result v128)
(i16x8.avgr_u
(local.get $0)
(local.get $1)
)
)
- (func $116 (param $0 v128) (result v128)
+ (func $130 (param $0 v128) (result v128)
(i32x4.abs
(local.get $0)
)
)
- (func $117 (param $0 v128) (result v128)
+ (func $131 (param $0 v128) (result v128)
(i32x4.neg
(local.get $0)
)
)
- (func $118 (param $0 v128) (result i32)
+ (func $132 (param $0 v128) (result i32)
(i32x4.any_true
(local.get $0)
)
)
- (func $119 (param $0 v128) (result i32)
+ (func $133 (param $0 v128) (result i32)
(i32x4.all_true
(local.get $0)
)
)
- (func $120 (param $0 v128) (result i32)
+ (func $134 (param $0 v128) (result i32)
(i32x4.bitmask
(local.get $0)
)
)
- (func $121 (param $0 v128) (param $1 i32) (result v128)
+ (func $135 (param $0 v128) (param $1 i32) (result v128)
(i32x4.shl
(local.get $0)
(local.get $1)
)
)
- (func $122 (param $0 v128) (param $1 i32) (result v128)
+ (func $136 (param $0 v128) (param $1 i32) (result v128)
(i32x4.shr_s
(local.get $0)
(local.get $1)
)
)
- (func $123 (param $0 v128) (param $1 i32) (result v128)
+ (func $137 (param $0 v128) (param $1 i32) (result v128)
(i32x4.shr_u
(local.get $0)
(local.get $1)
)
)
- (func $124 (param $0 v128) (param $1 v128) (result v128)
+ (func $138 (param $0 v128) (param $1 v128) (result v128)
(i32x4.add
(local.get $0)
(local.get $1)
)
)
- (func $125 (param $0 v128) (param $1 v128) (result v128)
+ (func $139 (param $0 v128) (param $1 v128) (result v128)
(i32x4.sub
(local.get $0)
(local.get $1)
)
)
- (func $126 (param $0 v128) (param $1 v128) (result v128)
+ (func $140 (param $0 v128) (param $1 v128) (result v128)
(i32x4.mul
(local.get $0)
(local.get $1)
)
)
- (func $127 (param $0 v128) (param $1 v128) (result v128)
+ (func $141 (param $0 v128) (param $1 v128) (result v128)
(i32x4.min_s
(local.get $0)
(local.get $1)
)
)
- (func $128 (param $0 v128) (param $1 v128) (result v128)
+ (func $142 (param $0 v128) (param $1 v128) (result v128)
(i32x4.min_u
(local.get $0)
(local.get $1)
)
)
- (func $129 (param $0 v128) (param $1 v128) (result v128)
+ (func $143 (param $0 v128) (param $1 v128) (result v128)
(i32x4.max_s
(local.get $0)
(local.get $1)
)
)
- (func $130 (param $0 v128) (param $1 v128) (result v128)
+ (func $144 (param $0 v128) (param $1 v128) (result v128)
(i32x4.max_u
(local.get $0)
(local.get $1)
)
)
- (func $131 (param $0 v128) (param $1 v128) (result v128)
+ (func $145 (param $0 v128) (param $1 v128) (result v128)
(i32x4.dot_i16x8_s
(local.get $0)
(local.get $1)
)
)
- (func $132 (param $0 v128) (result v128)
+ (func $146 (param $0 v128) (result v128)
(i64x2.neg
(local.get $0)
)
)
- (func $133 (param $0 v128) (result i32)
+ (func $147 (param $0 v128) (result i32)
(i64x2.any_true
(local.get $0)
)
)
- (func $134 (param $0 v128) (result i32)
+ (func $148 (param $0 v128) (result i32)
(i64x2.all_true
(local.get $0)
)
)
- (func $135 (param $0 v128) (param $1 i32) (result v128)
+ (func $149 (param $0 v128) (param $1 i32) (result v128)
(i64x2.shl
(local.get $0)
(local.get $1)
)
)
- (func $136 (param $0 v128) (param $1 i32) (result v128)
+ (func $150 (param $0 v128) (param $1 i32) (result v128)
(i64x2.shr_s
(local.get $0)
(local.get $1)
)
)
- (func $137 (param $0 v128) (param $1 i32) (result v128)
+ (func $151 (param $0 v128) (param $1 i32) (result v128)
(i64x2.shr_u
(local.get $0)
(local.get $1)
)
)
- (func $138 (param $0 v128) (param $1 v128) (result v128)
+ (func $152 (param $0 v128) (param $1 v128) (result v128)
(i64x2.add
(local.get $0)
(local.get $1)
)
)
- (func $139 (param $0 v128) (param $1 v128) (result v128)
+ (func $153 (param $0 v128) (param $1 v128) (result v128)
(i64x2.sub
(local.get $0)
(local.get $1)
)
)
- (func $140 (param $0 v128) (param $1 v128) (result v128)
+ (func $154 (param $0 v128) (param $1 v128) (result v128)
(i64x2.mul
(local.get $0)
(local.get $1)
)
)
- (func $141 (param $0 v128) (param $1 v128) (result v128)
+ (func $155 (param $0 v128) (param $1 v128) (result v128)
(f32x4.add
(local.get $0)
(local.get $1)
)
)
- (func $142 (param $0 v128) (param $1 v128) (result v128)
+ (func $156 (param $0 v128) (param $1 v128) (result v128)
(f32x4.sub
(local.get $0)
(local.get $1)
)
)
- (func $143 (param $0 v128) (param $1 v128) (result v128)
+ (func $157 (param $0 v128) (param $1 v128) (result v128)
(f32x4.mul
(local.get $0)
(local.get $1)
)
)
- (func $144 (param $0 v128) (param $1 v128) (result v128)
+ (func $158 (param $0 v128) (param $1 v128) (result v128)
(f32x4.div
(local.get $0)
(local.get $1)
)
)
- (func $145 (param $0 v128) (param $1 v128) (result v128)
+ (func $159 (param $0 v128) (param $1 v128) (result v128)
(f32x4.min
(local.get $0)
(local.get $1)
)
)
- (func $146 (param $0 v128) (param $1 v128) (result v128)
+ (func $160 (param $0 v128) (param $1 v128) (result v128)
(f32x4.max
(local.get $0)
(local.get $1)
)
)
- (func $147 (param $0 v128) (param $1 v128) (result v128)
+ (func $161 (param $0 v128) (param $1 v128) (result v128)
(f32x4.pmin
(local.get $0)
(local.get $1)
)
)
- (func $148 (param $0 v128) (param $1 v128) (result v128)
+ (func $162 (param $0 v128) (param $1 v128) (result v128)
(f32x4.pmax
(local.get $0)
(local.get $1)
)
)
- (func $149 (param $0 v128) (result v128)
+ (func $163 (param $0 v128) (result v128)
(f32x4.ceil
(local.get $0)
)
)
- (func $150 (param $0 v128) (result v128)
+ (func $164 (param $0 v128) (result v128)
(f32x4.floor
(local.get $0)
)
)
- (func $151 (param $0 v128) (result v128)
+ (func $165 (param $0 v128) (result v128)
(f32x4.trunc
(local.get $0)
)
)
- (func $152 (param $0 v128) (result v128)
+ (func $166 (param $0 v128) (result v128)
(f32x4.nearest
(local.get $0)
)
)
- (func $153 (param $0 v128) (result v128)
+ (func $167 (param $0 v128) (result v128)
(f32x4.abs
(local.get $0)
)
)
- (func $154 (param $0 v128) (result v128)
+ (func $168 (param $0 v128) (result v128)
(f32x4.neg
(local.get $0)
)
)
- (func $155 (param $0 v128) (result v128)
+ (func $169 (param $0 v128) (result v128)
(f32x4.sqrt
(local.get $0)
)
)
- (func $156 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
+ (func $170 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
(f32x4.qfma
(local.get $0)
(local.get $1)
(local.get $2)
)
)
- (func $157 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
+ (func $171 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
(f32x4.qfms
(local.get $0)
(local.get $1)
(local.get $2)
)
)
- (func $158 (param $0 v128) (param $1 v128) (result v128)
+ (func $172 (param $0 v128) (param $1 v128) (result v128)
(f64x2.add
(local.get $0)
(local.get $1)
)
)
- (func $159 (param $0 v128) (param $1 v128) (result v128)
+ (func $173 (param $0 v128) (param $1 v128) (result v128)
(f64x2.sub
(local.get $0)
(local.get $1)
)
)
- (func $160 (param $0 v128) (param $1 v128) (result v128)
+ (func $174 (param $0 v128) (param $1 v128) (result v128)
(f64x2.mul
(local.get $0)
(local.get $1)
)
)
- (func $161 (param $0 v128) (param $1 v128) (result v128)
+ (func $175 (param $0 v128) (param $1 v128) (result v128)
(f64x2.div
(local.get $0)
(local.get $1)
)
)
- (func $162 (param $0 v128) (param $1 v128) (result v128)
+ (func $176 (param $0 v128) (param $1 v128) (result v128)
(f64x2.min
(local.get $0)
(local.get $1)
)
)
- (func $163 (param $0 v128) (param $1 v128) (result v128)
+ (func $177 (param $0 v128) (param $1 v128) (result v128)
(f64x2.max
(local.get $0)
(local.get $1)
)
)
- (func $164 (param $0 v128) (param $1 v128) (result v128)
+ (func $178 (param $0 v128) (param $1 v128) (result v128)
(f64x2.pmin
(local.get $0)
(local.get $1)
)
)
- (func $165 (param $0 v128) (param $1 v128) (result v128)
+ (func $179 (param $0 v128) (param $1 v128) (result v128)
(f64x2.pmax
(local.get $0)
(local.get $1)
)
)
- (func $166 (param $0 v128) (result v128)
+ (func $180 (param $0 v128) (result v128)
(f64x2.ceil
(local.get $0)
)
)
- (func $167 (param $0 v128) (result v128)
+ (func $181 (param $0 v128) (result v128)
(f64x2.floor
(local.get $0)
)
)
- (func $168 (param $0 v128) (result v128)
+ (func $182 (param $0 v128) (result v128)
(f64x2.trunc
(local.get $0)
)
)
- (func $169 (param $0 v128) (result v128)
+ (func $183 (param $0 v128) (result v128)
(f64x2.nearest
(local.get $0)
)
)
- (func $170 (param $0 v128) (result v128)
+ (func $184 (param $0 v128) (result v128)
(f64x2.abs
(local.get $0)
)
)
- (func $171 (param $0 v128) (result v128)
+ (func $185 (param $0 v128) (result v128)
(f64x2.neg
(local.get $0)
)
)
- (func $172 (param $0 v128) (result v128)
+ (func $186 (param $0 v128) (result v128)
(f64x2.sqrt
(local.get $0)
)
)
- (func $173 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
+ (func $187 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
(f64x2.qfma
(local.get $0)
(local.get $1)
(local.get $2)
)
)
- (func $174 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
+ (func $188 (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
(f64x2.qfms
(local.get $0)
(local.get $1)
(local.get $2)
)
)
- (func $175 (param $0 v128) (result v128)
+ (func $189 (param $0 v128) (result v128)
(i32x4.trunc_sat_f32x4_s
(local.get $0)
)
)
- (func $176 (param $0 v128) (result v128)
+ (func $190 (param $0 v128) (result v128)
(i32x4.trunc_sat_f32x4_u
(local.get $0)
)
)
- (func $177 (param $0 v128) (result v128)
+ (func $191 (param $0 v128) (result v128)
(i64x2.trunc_sat_f64x2_s
(local.get $0)
)
)
- (func $178 (param $0 v128) (result v128)
+ (func $192 (param $0 v128) (result v128)
(i64x2.trunc_sat_f64x2_u
(local.get $0)
)
)
- (func $179 (param $0 v128) (result v128)
+ (func $193 (param $0 v128) (result v128)
(f32x4.convert_i32x4_s
(local.get $0)
)
)
- (func $180 (param $0 v128) (result v128)
+ (func $194 (param $0 v128) (result v128)
(f32x4.convert_i32x4_u
(local.get $0)
)
)
- (func $181 (param $0 v128) (result v128)
+ (func $195 (param $0 v128) (result v128)
(f64x2.convert_i64x2_s
(local.get $0)
)
)
- (func $182 (param $0 v128) (result v128)
+ (func $196 (param $0 v128) (result v128)
(f64x2.convert_i64x2_u
(local.get $0)
)
)
- (func $183 (param $0 i32) (result v128)
+ (func $197 (param $0 i32) (result v128)
(v8x16.load_splat
(local.get $0)
)
)
- (func $184 (param $0 i32) (result v128)
+ (func $198 (param $0 i32) (result v128)
(v16x8.load_splat
(local.get $0)
)
)
- (func $185 (param $0 i32) (result v128)
+ (func $199 (param $0 i32) (result v128)
(v32x4.load_splat
(local.get $0)
)
)
- (func $186 (param $0 i32) (result v128)
+ (func $200 (param $0 i32) (result v128)
(v64x2.load_splat
(local.get $0)
)
)
- (func $187 (param $0 v128) (param $1 v128) (result v128)
+ (func $201 (param $0 v128) (param $1 v128) (result v128)
(i8x16.narrow_i16x8_s
(local.get $0)
(local.get $1)
)
)
- (func $188 (param $0 v128) (param $1 v128) (result v128)
+ (func $202 (param $0 v128) (param $1 v128) (result v128)
(i8x16.narrow_i16x8_u
(local.get $0)
(local.get $1)
)
)
- (func $189 (param $0 v128) (param $1 v128) (result v128)
+ (func $203 (param $0 v128) (param $1 v128) (result v128)
(i16x8.narrow_i32x4_s
(local.get $0)
(local.get $1)
)
)
- (func $190 (param $0 v128) (param $1 v128) (result v128)
+ (func $204 (param $0 v128) (param $1 v128) (result v128)
(i16x8.narrow_i32x4_u
(local.get $0)
(local.get $1)
)
)
- (func $191 (param $0 v128) (result v128)
+ (func $205 (param $0 v128) (result v128)
(i16x8.widen_low_i8x16_s
(local.get $0)
)
)
- (func $192 (param $0 v128) (result v128)
+ (func $206 (param $0 v128) (result v128)
(i16x8.widen_high_i8x16_s
(local.get $0)
)
)
- (func $193 (param $0 v128) (result v128)
+ (func $207 (param $0 v128) (result v128)
(i16x8.widen_low_i8x16_u
(local.get $0)
)
)
- (func $194 (param $0 v128) (result v128)
+ (func $208 (param $0 v128) (result v128)
(i16x8.widen_high_i8x16_u
(local.get $0)
)
)
- (func $195 (param $0 v128) (result v128)
+ (func $209 (param $0 v128) (result v128)
(i32x4.widen_low_i16x8_s
(local.get $0)
)
)
- (func $196 (param $0 v128) (result v128)
+ (func $210 (param $0 v128) (result v128)
(i32x4.widen_high_i16x8_s
(local.get $0)
)
)
- (func $197 (param $0 v128) (result v128)
+ (func $211 (param $0 v128) (result v128)
(i32x4.widen_low_i16x8_u
(local.get $0)
)
)
- (func $198 (param $0 v128) (result v128)
+ (func $212 (param $0 v128) (result v128)
(i32x4.widen_high_i16x8_u
(local.get $0)
)
)
- (func $199 (param $0 i32) (result v128)
+ (func $213 (param $0 i32) (result v128)
(i16x8.load8x8_u
(local.get $0)
)
)
- (func $200 (param $0 i32) (result v128)
+ (func $214 (param $0 i32) (result v128)
(i16x8.load8x8_s
(local.get $0)
)
)
- (func $201 (param $0 i32) (result v128)
+ (func $215 (param $0 i32) (result v128)
(i32x4.load16x4_s
(local.get $0)
)
)
- (func $202 (param $0 i32) (result v128)
+ (func $216 (param $0 i32) (result v128)
(i32x4.load16x4_u
(local.get $0)
)
)
- (func $203 (param $0 i32) (result v128)
+ (func $217 (param $0 i32) (result v128)
(i64x2.load32x2_s
(local.get $0)
)
)
- (func $204 (param $0 i32) (result v128)
+ (func $218 (param $0 i32) (result v128)
(i64x2.load32x2_u
(local.get $0)
)
)
- (func $205 (param $0 i32) (result v128)
+ (func $219 (param $0 i32) (result v128)
(v128.load32_zero
(local.get $0)
)
)
- (func $206 (param $0 i32) (result v128)
+ (func $220 (param $0 i32) (result v128)
(v128.load64_zero
(local.get $0)
)
)
- (func $207 (param $0 v128) (param $1 v128) (result v128)
+ (func $221 (param $0 v128) (param $1 v128) (result v128)
(v8x16.swizzle
(local.get $0)
(local.get $1)
diff --git a/test/spec/simd.wast b/test/spec/simd.wast
index 5cc34d305..1d3f1b835 100644
--- a/test/spec/simd.wast
+++ b/test/spec/simd.wast
@@ -2,6 +2,7 @@
(memory 1)
(data (i32.const 128) "WASMSIMDGOESFAST")
(data (i32.const 256) "\80\90\a0\b0\c0\d0\e0\f0")
+ (data (i32.const 1024) "\ff\ff\ff\ff\ff\ff\ff\ff")
(func (export "v128.load") (param $0 i32) (result v128) (v128.load (local.get $0)))
(func (export "v128.store") (param $0 i32) (param $1 v128) (result v128)
(v128.store offset=0 align=16 (local.get $0) (local.get $1))
@@ -103,6 +104,14 @@
(func (export "v128.bitselect") (param $0 v128) (param $1 v128) (param $2 v128) (result v128)
(v128.bitselect (local.get $0) (local.get $1) (local.get $2))
)
+ (func (export "v128.load8_lane") (param $0 i32) (param $1 v128) (result v128) (v128.load8_lane 0 (local.get $0) (local.get $1)))
+ (func (export "v128.load16_lane") (param $0 i32) (param $1 v128) (result v128) (v128.load16_lane 0 (local.get $0) (local.get $1)))
+ (func (export "v128.load32_lane") (param $0 i32) (param $1 v128) (result v128) (v128.load32_lane 0 (local.get $0) (local.get $1)))
+ (func (export "v128.load64_lane") (param $0 i32) (param $1 v128) (result v128) (v128.load64_lane 0 (local.get $0) (local.get $1)))
+ (func (export "v128.store8_lane") (param $0 i32) (param $1 v128) (v128.store8_lane 0 (local.get $0) (local.get $1)))
+ (func (export "v128.store16_lane") (param $0 i32) (param $1 v128) (v128.store16_lane 0 (local.get $0) (local.get $1)))
+ (func (export "v128.store32_lane") (param $0 i32) (param $1 v128) (v128.store32_lane 0 (local.get $0) (local.get $1)))
+ (func (export "v128.store64_lane") (param $0 i32) (param $1 v128) (v128.store64_lane 0 (local.get $0) (local.get $1)))
(func (export "i8x16.abs") (param $0 v128) (result v128) (i8x16.abs (local.get $0)))
(func (export "i8x16.neg") (param $0 v128) (result v128) (i8x16.neg (local.get $0)))
(func (export "i8x16.any_true") (param $0 v128) (result i32) (i8x16.any_true (local.get $0)))
@@ -510,6 +519,56 @@
(v128.const i32x4 0xABABABAB 0xAAAAAAAA 0xBBBBBBBB 0xAABBAABB)
)
+;; load/store lane
+(assert_return (invoke "v128.load8_lane"
+ (i32.const 1024)
+ (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)
+ )
+ (v128.const i32x4 0x040302ff 0x08070605 0x0c0b0a09 0x100f0e0d)
+)
+(assert_return (invoke "v128.load16_lane"
+ (i32.const 1024)
+ (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)
+ )
+ (v128.const i32x4 0x0403ffff 0x08070605 0x0c0b0a09 0x100f0e0d)
+)
+(assert_return (invoke "v128.load32_lane"
+ (i32.const 1024)
+ (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)
+ )
+ (v128.const i32x4 0xffffffff 0x08070605 0x0c0b0a09 0x100f0e0d)
+)
+(assert_return (invoke "v128.load64_lane"
+ (i32.const 1024)
+ (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)
+ )
+ (v128.const i32x4 0xffffffff 0xffffffff 0x0c0b0a09 0x100f0e0d)
+)
+(assert_return (invoke "v128.store8_lane"
+ (i32.const 1024)
+ (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)
+ )
+)
+(assert_return (invoke "v128.load" (i32.const 1024)) (v128.const i32x4 0xffffff01 0xffffffff 0x00000000 0x00000000))
+(assert_return (invoke "v128.store16_lane"
+ (i32.const 1024)
+ (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)
+ )
+)
+(assert_return (invoke "v128.load" (i32.const 1024)) (v128.const i32x4 0xffff0201 0xffffffff 0x00000000 0x00000000))
+(assert_return (invoke "v128.store32_lane"
+ (i32.const 1024)
+ (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)
+ )
+)
+(assert_return (invoke "v128.load" (i32.const 1024)) (v128.const i32x4 0x04030201 0xffffffff 0x00000000 0x00000000))
+(assert_return (invoke "v128.store64_lane"
+ (i32.const 1024)
+ (v128.const i32x4 0x04030201 0x08070605 0x0c0b0a09 0x100f0e0d)
+ )
+)
+(assert_return (invoke "v128.load" (i32.const 1024)) (v128.const i32x4 0x04030201 0x08070605 0x00000000 0x00000000))
+
;; i8x16 arithmetic
(assert_return (invoke "i8x16.abs" (v128.const i8x16 0 1 42 -3 -56 127 -128 -126 0 -1 -42 3 56 -127 -128 126))
(v128.const i8x16 0 1 42 3 56 127 -128 126 0 1 42 3 56 127 -128 126)