summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wat-parser.cpp63
-rw-r--r--test/lit/wat-kitchen-sink.wast40
2 files changed, 98 insertions, 5 deletions
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index 0114d9477..10ca62de1 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -218,6 +218,18 @@ struct ParseInput {
return {};
}
+ std::optional<uint8_t> takeU8() {
+ if (auto t = peek()) {
+ if (auto n = t->getU32()) {
+ if (n <= std::numeric_limits<uint8_t>::max()) {
+ ++lexer;
+ return uint8_t(*n);
+ }
+ }
+ }
+ return {};
+ }
+
std::optional<double> takeF64() {
if (auto t = peek()) {
if (auto d = t->getF64()) {
@@ -591,6 +603,9 @@ struct NullInstrParserCtx {
InstrT makeGlobalGet(Index, GlobalT) { return Ok{}; }
InstrT makeGlobalSet(Index, GlobalT) { return Ok{}; }
+ InstrT makeSIMDExtract(Index, SIMDExtractOp, uint8_t) { return Ok{}; }
+ InstrT makeSIMDReplace(Index, SIMDReplaceOp, uint8_t) { return Ok{}; }
+ InstrT makeSIMDShuffle(Index, const std::array<uint8_t, 16>&) { return Ok{}; }
template<typename HeapTypeT> InstrT makeRefNull(Index, HeapTypeT) {
return {};
@@ -1328,6 +1343,28 @@ struct ParseDefsCtx : InstrParserCtx<ParseDefsCtx> {
CHECK_ERR(val);
return push(pos, builder.makeGlobalSet(global, *val));
}
+
+ Result<> makeSIMDExtract(Index pos, SIMDExtractOp op, uint8_t lane) {
+ auto val = pop(pos);
+ CHECK_ERR(val);
+ return push(pos, builder.makeSIMDExtract(op, *val, lane));
+ }
+
+ Result<> makeSIMDReplace(Index pos, SIMDReplaceOp op, uint8_t lane) {
+ auto val = pop(pos);
+ CHECK_ERR(val);
+ auto vec = pop(pos);
+ CHECK_ERR(vec);
+ return push(pos, builder.makeSIMDReplace(op, *vec, lane, *val));
+ }
+
+ Result<> makeSIMDShuffle(Index pos, const std::array<uint8_t, 16>& lanes) {
+ auto rhs = pop(pos);
+ CHECK_ERR(rhs);
+ auto lhs = pop(pos);
+ CHECK_ERR(lhs);
+ return push(pos, builder.makeSIMDShuffle(*lhs, *rhs, lanes));
+ }
};
// ================
@@ -1874,7 +1911,7 @@ template<typename Ctx> Result<typename Ctx::InstrsT> instrs(Ctx& ctx) {
}
if (ctx.in.getPos() != *end) {
- return ctx.in.err(start, "expected end of instruction");
+ return ctx.in.err("expected end of instruction");
}
} else {
WASM_UNREACHABLE("expected paren");
@@ -2068,19 +2105,35 @@ Result<typename Ctx::InstrT> makeAtomicFence(Ctx& ctx, Index pos) {
template<typename Ctx>
Result<typename Ctx::InstrT>
-makeSIMDExtract(Ctx& ctx, Index pos, SIMDExtractOp op, size_t lanes) {
- return ctx.in.err("unimplemented instruction");
+makeSIMDExtract(Ctx& ctx, Index pos, SIMDExtractOp op, size_t) {
+ auto lane = ctx.in.takeU8();
+ if (!lane) {
+ return ctx.in.err("expected lane index");
+ }
+ return ctx.makeSIMDExtract(pos, op, *lane);
}
template<typename Ctx>
Result<typename Ctx::InstrT>
makeSIMDReplace(Ctx& ctx, Index pos, SIMDReplaceOp op, size_t lanes) {
- return ctx.in.err("unimplemented instruction");
+ auto lane = ctx.in.takeU8();
+ if (!lane) {
+ return ctx.in.err("expected lane index");
+ }
+ return ctx.makeSIMDReplace(pos, op, *lane);
}
template<typename Ctx>
Result<typename Ctx::InstrT> makeSIMDShuffle(Ctx& ctx, Index pos) {
- return ctx.in.err("unimplemented instruction");
+ std::array<uint8_t, 16> lanes;
+ for (int i = 0; i < 16; ++i) {
+ auto lane = ctx.in.takeU8();
+ if (!lane) {
+ return ctx.in.err("expected lane index");
+ }
+ lanes[i] = *lane;
+ }
+ return ctx.makeSIMDShuffle(pos, lanes);
}
template<typename Ctx>
diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast
index 1ddaa610d..89f642838 100644
--- a/test/lit/wat-kitchen-sink.wast
+++ b/test/lit/wat-kitchen-sink.wast
@@ -25,6 +25,12 @@
;; CHECK: (type $i32_i32_i32_=>_none (func_subtype (param i32 i32 i32) func))
+ ;; CHECK: (type $v128_=>_i32 (func_subtype (param v128) (result i32) func))
+
+ ;; CHECK: (type $v128_i32_=>_v128 (func_subtype (param v128 i32) (result v128) func))
+
+ ;; CHECK: (type $v128_v128_=>_v128 (func_subtype (param v128 v128) (result v128) func))
+
;; CHECK: (rec
;; CHECK-NEXT: (type $s0 (struct_subtype data))
(type $s0 (sub (struct)))
@@ -703,6 +709,40 @@
global.set 4
)
+ ;; CHECK: (func $simd-extract (type $v128_=>_i32) (param $0 v128) (result i32)
+ ;; CHECK-NEXT: (i32x4.extract_lane 3
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $simd-extract (param v128) (result i32)
+ local.get 0
+ i32x4.extract_lane 3
+ )
+
+ ;; CHECK: (func $simd-replace (type $v128_i32_=>_v128) (param $0 v128) (param $1 i32) (result v128)
+ ;; CHECK-NEXT: (i32x4.replace_lane 2
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $simd-replace (param v128 i32) (result v128)
+ local.get 0
+ local.get 1
+ i32x4.replace_lane 2
+ )
+
+ ;; CHECK: (func $simd-shuffle (type $v128_v128_=>_v128) (param $0 v128) (param $1 v128) (result v128)
+ ;; CHECK-NEXT: (i8x16.shuffle 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $simd-shuffle (param v128 v128) (result v128)
+ local.get 0
+ local.get 1
+ i8x16.shuffle 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23
+ )
+
;; CHECK: (func $use-types (type $ref|$s0|_ref|$s1|_ref|$s2|_ref|$s3|_ref|$s4|_ref|$s5|_ref|$s6|_ref|$s7|_ref|$s8|_ref|$a0|_ref|$a1|_ref|$a2|_ref|$a3|_ref|$subvoid|_ref|$submany|_=>_none) (param $0 (ref $s0)) (param $1 (ref $s1)) (param $2 (ref $s2)) (param $3 (ref $s3)) (param $4 (ref $s4)) (param $5 (ref $s5)) (param $6 (ref $s6)) (param $7 (ref $s7)) (param $8 (ref $s8)) (param $9 (ref $a0)) (param $10 (ref $a1)) (param $11 (ref $a2)) (param $12 (ref $a3)) (param $13 (ref $subvoid)) (param $14 (ref $submany))
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )