summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp30
-rw-r--r--src/wasm/wasm-s-parser.cpp19
-rw-r--r--src/wasm/wasm-stack.cpp22
-rw-r--r--src/wasm/wasm-validator.cpp21
-rw-r--r--src/wasm/wasm.cpp22
5 files changed, 83 insertions, 31 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 4a82c84a9..64a40f2ca 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -3019,7 +3019,7 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (maybeVisitRefCast(curr, opcode)) {
break;
}
- if (maybeVisitBrOnCast(curr, opcode)) {
+ if (maybeVisitBrOn(curr, opcode)) {
break;
}
if (maybeVisitRttCanon(curr, opcode)) {
@@ -5825,17 +5825,31 @@ bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) {
return true;
}
-bool WasmBinaryBuilder::maybeVisitBrOnCast(Expression*& out, uint32_t code) {
- if (code != BinaryConsts::BrOnCast) {
- return false;
+bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) {
+ BrOnOp op;
+ switch (code) {
+ case BinaryConsts::BrOnCast:
+ op = BrOnCast;
+ break;
+ case BinaryConsts::BrOnFunc:
+ op = BrOnFunc;
+ break;
+ case BinaryConsts::BrOnData:
+ op = BrOnData;
+ break;
+ case BinaryConsts::BrOnI31:
+ op = BrOnI31;
+ break;
+ default:
+ return false;
}
auto name = getBreakTarget(getU32LEB()).name;
- auto* rtt = popNonVoidExpression();
- if (!rtt->type.isRtt()) {
- throwError("bad rtt for br_on_cast");
+ Expression* rtt = nullptr;
+ if (op == BrOnCast) {
+ rtt = popNonVoidExpression();
}
auto* ref = popNonVoidExpression();
- out = Builder(wasm).makeBrOnCast(name, ref, rtt);
+ out = Builder(wasm).makeBrOn(op, name, ref, rtt);
return true;
}
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 9cf2f3be9..3075f70d7 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2130,18 +2130,21 @@ Expression* SExpressionWasmBuilder::makeRefCast(Element& s) {
return Builder(wasm).makeRefCast(ref, rtt);
}
-Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s) {
+Expression* SExpressionWasmBuilder::makeBrOn(Element& s, BrOnOp op) {
auto name = getLabel(*s[1]);
auto* ref = parseExpression(*s[2]);
- auto* rtt = parseExpression(*s[3]);
+ Expression* rtt = nullptr;
Builder builder(wasm);
- if (rtt->type == Type::unreachable) {
- // An unreachable rtt is not supported: the text format does not provide the
- // type, so if it's unreachable we should not even create a br_on_cast in
- // such a case, as we'd have no idea what it casts to.
- return builder.makeSequence(builder.makeDrop(ref), rtt);
+ if (op == BrOnCast) {
+ rtt = parseExpression(*s[3]);
+ if (rtt->type == Type::unreachable) {
+ // An unreachable rtt is not supported: the text format does not provide
+ // the type, so if it's unreachable we should not even create a br_on_cast
+ // in such a case, as we'd have no idea what it casts to.
+ return builder.makeSequence(builder.makeDrop(ref), rtt);
+ }
}
- return builder.makeBrOnCast(name, ref, rtt);
+ return builder.makeBrOn(op, name, ref, rtt);
}
Expression* SExpressionWasmBuilder::makeRttCanon(Element& s) {
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 197581e33..0ccca0e23 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1990,9 +1990,25 @@ void BinaryInstWriter::visitRefCast(RefCast* curr) {
o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefCast);
}
-void BinaryInstWriter::visitBrOnCast(BrOnCast* curr) {
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnCast)
- << U32LEB(getBreakIndex(curr->name));
+void BinaryInstWriter::visitBrOn(BrOn* curr) {
+ o << int8_t(BinaryConsts::GCPrefix);
+ switch (curr->op) {
+ case BrOnCast:
+ o << U32LEB(BinaryConsts::BrOnCast);
+ break;
+ case BrOnFunc:
+ o << U32LEB(BinaryConsts::BrOnFunc);
+ break;
+ case BrOnData:
+ o << U32LEB(BinaryConsts::BrOnData);
+ break;
+ case BrOnI31:
+ o << U32LEB(BinaryConsts::BrOnI31);
+ break;
+ default:
+ WASM_UNREACHABLE("invalid br_on_*");
+ }
+ o << U32LEB(getBreakIndex(curr->name));
}
void BinaryInstWriter::visitRttCanon(RttCanon* curr) {
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index c6d0d9fe7..6a1b72476 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -344,7 +344,7 @@ public:
void visitI31Get(I31Get* curr);
void visitRefTest(RefTest* curr);
void visitRefCast(RefCast* curr);
- void visitBrOnCast(BrOnCast* curr);
+ void visitBrOn(BrOn* curr);
void visitRttCanon(RttCanon* curr);
void visitRttSub(RttSub* curr);
void visitStructNew(StructNew* curr);
@@ -2207,7 +2207,7 @@ void FunctionValidator::visitRefCast(RefCast* curr) {
}
}
-void FunctionValidator::visitBrOnCast(BrOnCast* curr) {
+void FunctionValidator::visitBrOn(BrOn* curr) {
shouldBeTrue(getModule()->features.hasGC(),
curr,
"br_on_cast requires gc to be enabled");
@@ -2215,12 +2215,17 @@ void FunctionValidator::visitBrOnCast(BrOnCast* curr) {
shouldBeTrue(
curr->ref->type.isRef(), curr, "br_on_cast ref must have ref type");
}
- // Note that an unreachable rtt is not supported: the text and binary formats
- // do not provide the type, so if it's unreachable we should not even create
- // a br_on_cast in such a case, as we'd have no idea what it casts to.
- shouldBeTrue(
- curr->rtt->type.isRtt(), curr, "br_on_cast rtt must have rtt type");
- noteBreak(curr->name, curr->getCastType(), curr);
+ if (curr->op == BrOnCast) {
+ // Note that an unreachable rtt is not supported: the text and binary
+ // formats do not provide the type, so if it's unreachable we should not
+ // even create a br_on_cast in such a case, as we'd have no idea what it
+ // casts to.
+ shouldBeTrue(
+ curr->rtt->type.isRtt(), curr, "br_on_cast rtt must have rtt type");
+ noteBreak(curr->name, curr->getCastType(), curr);
+ } else {
+ shouldBeTrue(curr->rtt == nullptr, curr, "non-cast BrOn must not have rtt");
+ }
}
void FunctionValidator::visitRttCanon(RttCanon* curr) {
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 1e4ff6e3e..a62435412 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -931,15 +931,29 @@ void RefCast::finalize() {
Type RefCast::getCastType() { return doGetCastType(this); }
-void BrOnCast::finalize() {
- if (ref->type == Type::unreachable || rtt->type == Type::unreachable) {
+void BrOn::finalize() {
+ if (ref->type == Type::unreachable ||
+ (rtt && rtt->type == Type::unreachable)) {
type = Type::unreachable;
} else {
type = ref->type;
}
}
-Type BrOnCast::getCastType() { return Type(rtt->type.getHeapType(), Nullable); }
+Type BrOn::getCastType() {
+ switch (op) {
+ case BrOnCast:
+ return Type(rtt->type.getHeapType(), Nullable);
+ case BrOnFunc:
+ return Type::funcref;
+ case BrOnData:
+ return Type::dataref;
+ case BrOnI31:
+ return Type::i31ref;
+ default:
+ WASM_UNREACHABLE("invalid br_on_*");
+ }
+}
void RttCanon::finalize() {
// Nothing to do - the type must have been set already during construction.
@@ -1032,7 +1046,7 @@ void RefAs::finalize() {
type = Type::i31ref;
break;
default:
- WASM_UNREACHABLE("unimplemented ref.is_*");
+ WASM_UNREACHABLE("invalid ref.as_*");
}
}