summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wat-parser.cpp44
-rw-r--r--test/lit/wat-kitchen-sink.wast66
2 files changed, 108 insertions, 2 deletions
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index 16f33d2d7..8aab01029 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -722,6 +722,9 @@ struct NullInstrParserCtx {
return Ok{};
}
+ InstrT makeMemoryCopy(Index, MemoryT*, MemoryT*) { return Ok{}; }
+ InstrT makeMemoryFill(Index, MemoryT*) { return Ok{}; }
+
template<typename HeapTypeT> InstrT makeRefNull(Index, HeapTypeT) {
return {};
}
@@ -1690,6 +1693,33 @@ struct ParseDefsCtx : InstrParserCtx<ParseDefsCtx> {
builder.makeSIMDLoadStoreLane(
op, memarg.offset, memarg.align, lane, *ptr, *vec, *m));
}
+
+ Result<> makeMemoryCopy(Index pos, Name* destMem, Name* srcMem) {
+ auto destMemory = self().getMemory(pos, destMem);
+ CHECK_ERR(destMemory);
+ auto srcMemory = self().getMemory(pos, srcMem);
+ CHECK_ERR(srcMemory);
+ auto size = pop(pos);
+ CHECK_ERR(size);
+ auto src = pop(pos);
+ CHECK_ERR(src);
+ auto dest = pop(pos);
+ CHECK_ERR(dest);
+ return push(
+ pos, builder.makeMemoryCopy(*dest, *src, *size, *destMemory, *srcMemory));
+ }
+
+ Result<> makeMemoryFill(Index pos, Name* mem) {
+ auto m = self().getMemory(pos, mem);
+ CHECK_ERR(m);
+ auto size = pop(pos);
+ CHECK_ERR(size);
+ auto val = pop(pos);
+ CHECK_ERR(val);
+ auto dest = pop(pos);
+ CHECK_ERR(dest);
+ return push(pos, builder.makeMemoryFill(*dest, *val, *size, *m));
+ }
};
// ================
@@ -2607,12 +2637,22 @@ Result<typename Ctx::InstrT> makeDataDrop(Ctx& ctx, Index pos) {
template<typename Ctx>
Result<typename Ctx::InstrT> makeMemoryCopy(Ctx& ctx, Index pos) {
- return ctx.in.err("unimplemented instruction");
+ auto destMem = maybeMemidx(ctx);
+ CHECK_ERR(destMem);
+ std::optional<typename Ctx::MemoryT> srcMem = std::nullopt;
+ if (destMem) {
+ auto mem = memidx(ctx);
+ CHECK_ERR(mem);
+ srcMem = *mem;
+ }
+ return ctx.makeMemoryCopy(pos, destMem.getPtr(), srcMem ? &*srcMem : nullptr);
}
template<typename Ctx>
Result<typename Ctx::InstrT> makeMemoryFill(Ctx& ctx, Index pos) {
- return ctx.in.err("unimplemented instruction");
+ auto mem = maybeMemidx(ctx);
+ CHECK_ERR(mem);
+ return ctx.makeMemoryFill(pos, mem.getPtr());
}
template<typename Ctx>
diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast
index 4c1ac92e7..e621961a7 100644
--- a/test/lit/wat-kitchen-sink.wast
+++ b/test/lit/wat-kitchen-sink.wast
@@ -37,6 +37,8 @@
;; CHECK: (type $i32_i64_v128_=>_none (func_subtype (param i32 i64 v128) func))
+ ;; CHECK: (type $i32_i32_i64_i64_=>_none (func_subtype (param i32 i32 i64 i64) func))
+
;; CHECK: (rec
;; CHECK-NEXT: (type $s0 (struct_subtype data))
(type $s0 (sub (struct)))
@@ -1057,6 +1059,70 @@
v128.store64_lane 3 align=4 0
)
+ ;; CHECK: (func $memory-copy (type $i32_i32_i64_i64_=>_none) (param $0 i32) (param $1 i32) (param $2 i64) (param $3 i64)
+ ;; CHECK-NEXT: (memory.copy $mem $mem
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (memory.copy $mem $mem-i32
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (memory.copy $mem-i64 $mem-i64
+ ;; CHECK-NEXT: (local.get $2)
+ ;; CHECK-NEXT: (local.get $3)
+ ;; CHECK-NEXT: (i64.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $memory-copy (param i32 i32 i64 i64)
+ local.get 0
+ local.get 1
+ i32.const 2
+ memory.copy
+ local.get 0
+ local.get 1
+ i32.const 3
+ memory.copy 0 $mem-i32
+ local.get 2
+ local.get 3
+ i64.const 4
+ memory.copy $mem-i64 3
+ )
+
+ ;; CHECK: (func $memory-fill (type $i32_i64_=>_none) (param $0 i32) (param $1 i64)
+ ;; CHECK-NEXT: (memory.fill $mem
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (memory.fill $mem
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: (i32.const 3)
+ ;; CHECK-NEXT: (i32.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (memory.fill $mem-i64
+ ;; CHECK-NEXT: (local.get $1)
+ ;; CHECK-NEXT: (i32.const 5)
+ ;; CHECK-NEXT: (i64.const 6)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $memory-fill (param i32 i64)
+ local.get 0
+ i32.const 1
+ i32.const 2
+ memory.fill
+ local.get 0
+ i32.const 3
+ i32.const 4
+ memory.fill 0
+ local.get 1
+ i32.const 5
+ i64.const 6
+ memory.fill $mem-i64
+ )
+
;; 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: )