summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2023-11-15 01:44:27 +0100
committerGitHub <noreply@github.com>2023-11-15 01:44:27 +0100
commitb01c950bff78d44b31de0239ba0a27a9c3d33345 (patch)
tree2092499bffd4abcd01032c08dd392b1c4b35461c
parent325d588b0bf1497322d75c35ef8e017f9a8a5d7c (diff)
downloadbinaryen-b01c950bff78d44b31de0239ba0a27a9c3d33345.tar.gz
binaryen-b01c950bff78d44b31de0239ba0a27a9c3d33345.tar.bz2
binaryen-b01c950bff78d44b31de0239ba0a27a9c3d33345.zip
[Parser] Parse BrOn expressions (#6100)
-rw-r--r--src/parser/contexts.h11
-rw-r--r--src/parser/parsers.h10
-rw-r--r--src/wasm-ir-builder.h3
-rw-r--r--src/wasm.h1
-rw-r--r--src/wasm/wasm-ir-builder.cpp18
-rw-r--r--test/lit/wat-kitchen-sink.wast108
6 files changed, 129 insertions, 22 deletions
diff --git a/src/parser/contexts.h b/src/parser/contexts.h
index bf6c291e7..4147f7bda 100644
--- a/src/parser/contexts.h
+++ b/src/parser/contexts.h
@@ -398,6 +398,12 @@ struct NullInstrParserCtx {
template<typename TypeT> Result<> makeRefTest(Index, TypeT) { return Ok{}; }
template<typename TypeT> Result<> makeRefCast(Index, TypeT) { return Ok{}; }
+ Result<> makeBrOn(Index, LabelIdxT, BrOnOp) { return Ok{}; }
+
+ template<typename TypeT> Result<> makeBrOn(Index, LabelIdxT, BrOnOp, TypeT) {
+ return Ok{};
+ }
+
template<typename HeapTypeT> Result<> makeStructNew(Index, HeapTypeT) {
return Ok{};
}
@@ -1290,6 +1296,11 @@ struct ParseDefsCtx : TypeParserCtx<ParseDefsCtx> {
return withLoc(pos, irBuilder.makeRefCast(type));
}
+ Result<>
+ makeBrOn(Index pos, Index label, BrOnOp op, Type castType = Type::none) {
+ return withLoc(pos, irBuilder.makeBrOn(label, op, castType));
+ }
+
Result<> makeStructNew(Index pos, HeapType type) {
return withLoc(pos, irBuilder.makeStructNew(type));
}
diff --git a/src/parser/parsers.h b/src/parser/parsers.h
index 6b6bb0aa5..e2fb3732a 100644
--- a/src/parser/parsers.h
+++ b/src/parser/parsers.h
@@ -1315,11 +1315,17 @@ template<typename Ctx> Result<> makeRefCast(Ctx& ctx, Index pos) {
}
template<typename Ctx> Result<> makeBrOnNull(Ctx& ctx, Index pos, bool onFail) {
- return ctx.in.err("unimplemented instruction");
+ auto label = labelidx(ctx);
+ CHECK_ERR(label);
+ return ctx.makeBrOn(pos, *label, onFail ? BrOnNonNull : BrOnNull);
}
template<typename Ctx> Result<> makeBrOnCast(Ctx& ctx, Index pos, bool onFail) {
- return ctx.in.err("unimplemented instruction");
+ auto label = labelidx(ctx);
+ CHECK_ERR(label);
+ auto type = reftype(ctx);
+ CHECK_ERR(type);
+ return ctx.makeBrOn(pos, *label, onFail ? BrOnCastFail : BrOnCast, *type);
}
template<typename Ctx>
diff --git a/src/wasm-ir-builder.h b/src/wasm-ir-builder.h
index c0cd7b4a1..64ee0d62e 100644
--- a/src/wasm-ir-builder.h
+++ b/src/wasm-ir-builder.h
@@ -151,7 +151,8 @@ public:
// [[nodiscard]] Result<> makeCallRef();
[[nodiscard]] Result<> makeRefTest(Type type);
[[nodiscard]] Result<> makeRefCast(Type type);
- // [[nodiscard]] Result<> makeBrOn();
+ [[nodiscard]] Result<>
+ makeBrOn(Index label, BrOnOp op, Type castType = Type::none);
[[nodiscard]] Result<> makeStructNew(HeapType type);
[[nodiscard]] Result<> makeStructNewDefault(HeapType type);
[[nodiscard]] Result<>
diff --git a/src/wasm.h b/src/wasm.h
index 96c9271fe..dbedc05f4 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1566,6 +1566,7 @@ public:
class BrOn : public SpecificExpression<Expression::BrOnId> {
public:
+ BrOn() = default;
BrOn(MixedArena& allocator) {}
BrOnOp op;
diff --git a/src/wasm/wasm-ir-builder.cpp b/src/wasm/wasm-ir-builder.cpp
index c973238e9..cc2bfb433 100644
--- a/src/wasm/wasm-ir-builder.cpp
+++ b/src/wasm/wasm-ir-builder.cpp
@@ -220,18 +220,15 @@ Result<> IRBuilder::visitExpression(Expression* curr) {
#define DELEGATE_FIELD_CHILD_VECTOR(id, field) \
WASM_UNREACHABLE("should have called visit" #id " because " #id \
" has child vector " #field);
-#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field) \
- WASM_UNREACHABLE("should have called visit" #id " because " #id \
- " has scope name use " #field);
-#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field) \
- WASM_UNREACHABLE("should have called visit" #id " because " #id \
- " has scope name use vector " #field);
#define DELEGATE_FIELD_INT(id, field)
#define DELEGATE_FIELD_INT_ARRAY(id, field)
#define DELEGATE_FIELD_LITERAL(id, field)
#define DELEGATE_FIELD_NAME(id, field)
#define DELEGATE_FIELD_NAME_VECTOR(id, field)
+#define DELEGATE_FIELD_SCOPE_NAME_USE(id, field)
+#define DELEGATE_FIELD_SCOPE_NAME_USE_VECTOR(id, field)
+
#define DELEGATE_FIELD_TYPE(id, field)
#define DELEGATE_FIELD_HEAPTYPE(id, field)
#define DELEGATE_FIELD_ADDRESS(id, field)
@@ -933,7 +930,14 @@ Result<> IRBuilder::makeRefCast(Type type) {
return Ok{};
}
-// Result<> IRBuilder::makeBrOn() {}
+Result<> IRBuilder::makeBrOn(Index label, BrOnOp op, Type castType) {
+ BrOn curr;
+ CHECK_ERR(visitBrOn(&curr));
+ auto name = getLabelName(label);
+ CHECK_ERR(name);
+ push(builder.makeBrOn(op, *name, curr.ref, castType));
+ return Ok{};
+}
Result<> IRBuilder::makeStructNew(HeapType type) {
StructNew curr(wasm.allocator);
diff --git a/test/lit/wat-kitchen-sink.wast b/test/lit/wat-kitchen-sink.wast
index 77c31c7e1..a99cd4c24 100644
--- a/test/lit/wat-kitchen-sink.wast
+++ b/test/lit/wat-kitchen-sink.wast
@@ -23,13 +23,13 @@
;; CHECK: (type $a2 (array (mut f32)))
- ;; CHECK: (type $8 (func (param i32)))
+ ;; CHECK: (type $8 (func (param anyref)))
- ;; CHECK: (type $9 (func (param i32 i32 i32)))
+ ;; CHECK: (type $9 (func (param i32)))
- ;; CHECK: (type $10 (func (param v128 i32) (result v128)))
+ ;; CHECK: (type $10 (func (param i32 i32 i32)))
- ;; CHECK: (type $11 (func (param anyref)))
+ ;; CHECK: (type $11 (func (param v128 i32) (result v128)))
;; CHECK: (rec
;; CHECK-NEXT: (type $s0 (struct ))
@@ -234,11 +234,11 @@
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
- ;; CHECK: (func $f1 (type $8) (param $0 i32)
+ ;; CHECK: (func $f1 (type $9) (param $0 i32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $f1 (param i32))
- ;; CHECK: (func $f2 (type $8) (param $x i32)
+ ;; CHECK: (func $f2 (type $9) (param $x i32)
;; CHECK-NEXT: (nop)
;; CHECK-NEXT: )
(func $f2 (param $x i32))
@@ -1756,7 +1756,7 @@
drop
)
- ;; CHECK: (func $select (type $9) (param $0 i32) (param $1 i32) (param $2 i32)
+ ;; CHECK: (func $select (type $10) (param $0 i32) (param $1 i32) (param $2 i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (select
;; CHECK-NEXT: (local.get $0)
@@ -2048,7 +2048,7 @@
i32x4.extract_lane 3
)
- ;; CHECK: (func $simd-replace (type $10) (param $0 v128) (param $1 i32) (result v128)
+ ;; CHECK: (func $simd-replace (type $11) (param $0 v128) (param $1 i32) (result v128)
;; CHECK-NEXT: (i32x4.replace_lane 2
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (local.get $1)
@@ -2086,7 +2086,7 @@
v128.bitselect
)
- ;; CHECK: (func $simd-shift (type $10) (param $0 v128) (param $1 i32) (result v128)
+ ;; CHECK: (func $simd-shift (type $11) (param $0 v128) (param $1 i32) (result v128)
;; CHECK-NEXT: (i8x16.shl
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (local.get $1)
@@ -2141,7 +2141,7 @@
v128.store64_lane 3 align=4 0
)
- ;; CHECK: (func $memory-init (type $9) (param $0 i32) (param $1 i32) (param $2 i32)
+ ;; CHECK: (func $memory-init (type $10) (param $0 i32) (param $1 i32) (param $2 i32)
;; CHECK-NEXT: (memory.init $mem-i32 $passive
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (local.get $1)
@@ -2376,7 +2376,7 @@
drop
)
- ;; CHECK: (func $ref-test (type $11) (param $0 anyref)
+ ;; CHECK: (func $ref-test (type $8) (param $0 anyref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.test i31ref
;; CHECK-NEXT: (local.get $0)
@@ -2397,7 +2397,7 @@
drop
)
- ;; CHECK: (func $ref-cast (type $11) (param $0 anyref)
+ ;; CHECK: (func $ref-cast (type $8) (param $0 anyref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (ref.cast i31ref
;; CHECK-NEXT: (local.get $0)
@@ -2418,6 +2418,90 @@
drop
)
+ ;; CHECK: (func $br-on-null (type $8) (param $0 anyref)
+ ;; CHECK-NEXT: (block $label
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (br_on_null $label
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $br-on-null (param anyref)
+ local.get 0
+ br_on_null 0
+ drop
+ )
+
+ ;; CHECK: (func $br-on-non-null (type $8) (param $0 anyref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block $label (result (ref any))
+ ;; CHECK-NEXT: (br_on_non_null $label
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $br-on-non-null (param anyref)
+ block (result (ref any))
+ local.get 0
+ br_on_non_null 0
+ unreachable
+ end
+ drop
+ )
+
+ ;; CHECK: (func $br-on-cast (type $8) (param $0 anyref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block $label (result i31ref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result (ref any))
+ ;; CHECK-NEXT: (br_on_cast $label anyref i31ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $br-on-cast (param anyref)
+ block (result i31ref)
+ block (result (ref any))
+ local.get 0
+ br_on_cast 1 i31ref
+ end
+ unreachable
+ end
+ drop
+ )
+
+ ;; CHECK: (func $br-on-cast-fail (type $8) (param $0 anyref)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block $label (result (ref any))
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i31ref)
+ ;; CHECK-NEXT: (br_on_cast_fail $label anyref i31ref
+ ;; CHECK-NEXT: (local.get $0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $br-on-cast-fail (param anyref)
+ block (result (ref any))
+ block (result i31ref)
+ local.get 0
+ br_on_cast_fail 1 i31ref
+ end
+ unreachable
+ end
+ drop
+ )
+
;; CHECK: (func $struct-new (type $34) (param $0 i32) (param $1 i64) (result (ref $pair))
;; CHECK-NEXT: (struct.new $pair
;; CHECK-NEXT: (local.get $0)