summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/parser/contexts.h5
-rw-r--r--src/parser/parsers.h4
-rw-r--r--src/wasm-ir-builder.h3
-rw-r--r--src/wasm/wasm-ir-builder.cpp24
-rw-r--r--test/lit/wat-kitchen-sink.wast67
5 files changed, 77 insertions, 26 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h
index 73be5e46e..c1ccefe53 100644
--- a/src/parser/contexts.h
+++ b/src/parser/contexts.h
@@ -440,6 +440,7 @@ struct NullInstrParserCtx {
Result<> makeMemoryCopy(Index, MemoryIdxT*, MemoryIdxT*) { return Ok{}; }
Result<> makeMemoryFill(Index, MemoryIdxT*) { return Ok{}; }
+ template<typename TypeT> Result<> makePop(Index, TypeT) { return Ok{}; }
Result<> makeCall(Index, FuncIdxT, bool) { return Ok{}; }
template<typename TypeUseT>
Result<> makeCallIndirect(Index, TableIdxT*, TypeUseT, bool) {
@@ -1649,6 +1650,10 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return withLoc(pos, irBuilder.makeMemoryFill(*m));
}
+ Result<> makePop(Index pos, Type type) {
+ return withLoc(pos, irBuilder.makePop(type));
+ }
+
Result<> makeCall(Index pos, Name func, bool isReturn) {
return withLoc(pos, irBuilder.makeCall(func, isReturn));
}
diff --git a/src/parser/parsers.h b/src/parser/parsers.h
index 706c6525e..c7b9168b1 100644
--- a/src/parser/parsers.h
+++ b/src/parser/parsers.h
@@ -1555,7 +1555,9 @@ template<typename Ctx> Result<> makeMemoryFill(Ctx& ctx, Index pos) {
}
template<typename Ctx> Result<> makePop(Ctx& ctx, Index pos) {
- return ctx.in.err("unimplemented instruction");
+ auto type = valtype(ctx);
+ CHECK_ERR(type);
+ return ctx.makePop(pos, *type);
}
template<typename Ctx> Result<> makeCall(Ctx& ctx, Index pos, bool isReturn) {
diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h
index fce8bd431..d32dfebf2 100644
--- a/src/wasm-ir-builder.h
+++ b/src/wasm-ir-builder.h
@@ -145,7 +145,7 @@ public:
[[nodiscard]] Result<> makeMemorySize(Name mem);
[[nodiscard]] Result<> makeMemoryGrow(Name mem);
[[nodiscard]] Result<> makeUnreachable();
- // [[nodiscard]] Result<> makePop();
+ [[nodiscard]] Result<> makePop(Type type);
[[nodiscard]] Result<> makeRefNull(HeapType type);
[[nodiscard]] Result<> makeRefIsNull();
[[nodiscard]] Result<> makeRefFunc(Name func);
@@ -232,6 +232,7 @@ public:
[[nodiscard]] Result<>
visitTupleExtract(TupleExtract*,
std::optional<uint32_t> arity = std::nullopt);
+ [[nodiscard]] Result<> visitPop(Pop*);
private:
Module& wasm;
diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp
index 1eea777e0..f8c8cf0a0 100644
--- a/src/wasm/wasm-ir-builder.cpp
+++ b/src/wasm/wasm-ir-builder.cpp
@@ -604,6 +604,12 @@ Result<> IRBuilder::visitTupleExtract(TupleExtract* curr,
return Ok{};
}
+Result<> IRBuilder::visitPop(Pop*) {
+ // Do not actually push this pop onto the stack since we generate our own pops
+ // as necessary when visiting the beginnings of try blocks.
+ return Ok{};
+}
+
Result<> IRBuilder::visitFunctionStart(Function* func) {
if (!scopeStack.empty()) {
return Err{"unexpected start of function"};
@@ -1300,7 +1306,23 @@ Result<> IRBuilder::makeUnreachable() {
return Ok{};
}
-// Result<> IRBuilder::makePop() {}
+Result<> IRBuilder::makePop(Type type) {
+ // We don't actually want to create a new Pop expression here because we
+ // already create them automatically when starting a legacy catch block that
+ // needs one. Just verify that the Pop we are being asked to make is the same
+ // type as the Pop we have already made.
+ auto& scope = getScope();
+ if (!scope.getCatch() || scope.exprStack.size() != 1 ||
+ !scope.exprStack[0]->is<Pop>()) {
+ return Err{
+ "pop instructions may only appear at the beginning of catch blocks"};
+ }
+ auto expectedType = scope.exprStack[0]->type;
+ if (type != expectedType) {
+ return Err{std::string("Expected pop of type ") + expectedType.toString()};
+ }
+ return Ok{};
+}
Result<> IRBuilder::makeRefNull(HeapType type) {
push(builder.makeRefNull(type));
diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast
index 638d80004..680468935 100644
--- a/test/lit/wat-kitchen-sink.wast
+++ b/test/lit/wat-kitchen-sink.wast
@@ -13,11 +13,11 @@
(type $ret2 (func (result i32 i32)))
(rec
- ;; CHECK: (type $pair (struct (field (mut i32)) (field (mut i64))))
+ ;; CHECK: (type $3 (func (result i32 i64)))
- ;; CHECK: (type $4 (func (param i32 i64)))
+ ;; CHECK: (type $pair (struct (field (mut i32)) (field (mut i64))))
- ;; CHECK: (type $5 (func (result i32 i64)))
+ ;; CHECK: (type $5 (func (param i32 i64)))
;; CHECK: (type $a2 (array (mut f32)))
@@ -1815,8 +1815,8 @@
end
)
- ;; CHECK: (func $try-catch-params (type $5) (result i32 i64)
- ;; CHECK-NEXT: (try (type $5) (result i32 i64)
+ ;; CHECK: (func $try-catch-params (type $3) (result i32 i64)
+ ;; CHECK-NEXT: (try (type $3) (result i32 i64)
;; CHECK-NEXT: (do
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i32.const 0)
@@ -1836,6 +1836,27 @@
end
)
+ ;; CHECK: (func $try-catch-pop (type $3) (result i32 i64)
+ ;; CHECK-NEXT: (try (type $3) (result i32 i64)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $tag-pair
+ ;; CHECK-NEXT: (pop (tuple i32 i64))
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-catch-pop (result i32 i64)
+ try (result i32 i64)
+ i32.const 0
+ i64.const 1
+ catch $tag-pair
+ pop (tuple i32 i64)
+ end
+ )
;; CHECK: (func $try-catch_all (type $void)
;; CHECK-NEXT: (try
@@ -2674,8 +2695,8 @@
br 0
)
- ;; CHECK: (func $br-multivalue (type $5) (result i32 i64)
- ;; CHECK-NEXT: (block $label (type $5) (result i32 i64)
+ ;; CHECK: (func $br-multivalue (type $3) (result i32 i64)
+ ;; CHECK-NEXT: (block $label (type $3) (result i32 i64)
;; CHECK-NEXT: (br $label
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i32.const 0)
@@ -2690,9 +2711,9 @@
br 0
)
- ;; CHECK: (func $br-multivalue-drop (type $5) (result i32 i64)
- ;; CHECK-NEXT: (block $label (type $5) (result i32 i64)
- ;; CHECK-NEXT: (block (type $5) (result i32 i64)
+ ;; CHECK: (func $br-multivalue-drop (type $3) (result i32 i64)
+ ;; CHECK-NEXT: (block $label (type $3) (result i32 i64)
+ ;; CHECK-NEXT: (block (type $3) (result i32 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (f32.const 0)
;; CHECK-NEXT: )
@@ -2892,9 +2913,9 @@
end
)
- ;; CHECK: (func $br-table-multivalue (type $5) (result i32 i64)
- ;; CHECK-NEXT: (block $a (type $5) (result i32 i64)
- ;; CHECK-NEXT: (block $b (type $5) (result i32 i64)
+ ;; CHECK: (func $br-table-multivalue (type $3) (result i32 i64)
+ ;; CHECK-NEXT: (block $a (type $3) (result i32 i64)
+ ;; CHECK-NEXT: (block $b (type $3) (result i32 i64)
;; CHECK-NEXT: (br_table $a $b
;; CHECK-NEXT: (tuple.make 2
;; CHECK-NEXT: (i32.const 42)
@@ -3049,7 +3070,7 @@
drop
)
- ;; CHECK: (func $memory-grow (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $memory-grow (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (memory.grow $mimport$0
;; CHECK-NEXT: (local.get $0)
@@ -3107,7 +3128,7 @@
global.set $pair
)
- ;; CHECK: (func $load (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $load (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.load $mimport$0 offset=42
;; CHECK-NEXT: (local.get $0)
@@ -3136,7 +3157,7 @@
drop
)
- ;; CHECK: (func $store (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $store (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (i32.store $mimport$0 offset=42 align=1
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const 0)
@@ -3162,7 +3183,7 @@
f32.store $mem-i64
)
- ;; CHECK: (func $atomic-rmw (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $atomic-rmw (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.atomic.rmw16.add_u $mimport$0
;; CHECK-NEXT: (local.get $0)
@@ -3187,7 +3208,7 @@
drop
)
- ;; CHECK: (func $atomic-cmpxchg (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $atomic-cmpxchg (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (i32.atomic.rmw8.cmpxchg_u $mem
;; CHECK-NEXT: (local.get $0)
@@ -3216,7 +3237,7 @@
drop
)
- ;; CHECK: (func $atomic-wait (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $atomic-wait (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (memory.atomic.wait32 $mimport$0
;; CHECK-NEXT: (local.get $0)
@@ -3245,7 +3266,7 @@
drop
)
- ;; CHECK: (func $atomic-notify (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $atomic-notify (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (memory.atomic.notify $mimport$0 offset=8
;; CHECK-NEXT: (local.get $0)
@@ -3337,7 +3358,7 @@
i8x16.shl
)
- ;; CHECK: (func $simd-load (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $simd-load (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (v128.load8x8_s $mimport$0 offset=8
;; CHECK-NEXT: (local.get $0)
@@ -3453,7 +3474,7 @@
memory.copy $mem-i64 5
)
- ;; CHECK: (func $memory-fill (type $4) (param $0 i32) (param $1 i64)
+ ;; CHECK: (func $memory-fill (type $5) (param $0 i32) (param $1 i64)
;; CHECK-NEXT: (memory.fill $mimport$0
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const 1)
@@ -3568,7 +3589,7 @@
(func $ref-func
ref.func $ref-func
drop
- ref.func 153
+ ref.func 154
drop
)