diff options
-rw-r--r-- | src/wasm/wat-parser.cpp | 63 | ||||
-rw-r--r-- | test/lit/wat-kitchen-sink.wast | 40 |
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: ) |