diff options
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) |