summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp35
-rw-r--r--src/wasm/wasm-s-parser.cpp18
-rw-r--r--src/wasm/wasm-stack.cpp79
-rw-r--r--src/wasm/wasm.cpp25
-rw-r--r--src/wasm/wat-parser.cpp13
5 files changed, 94 insertions, 76 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 61fd65eab..2639599d5 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -6930,8 +6930,8 @@ bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) {
}
bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) {
+ Type castType = Type::none;
BrOnOp op;
- auto nullability = NonNullable;
switch (code) {
case BinaryConsts::BrOnNull:
op = BrOnNull;
@@ -6941,44 +6941,47 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) {
break;
case BinaryConsts::BrOnCastStatic:
case BinaryConsts::BrOnCast:
+ case BinaryConsts::BrOnCastNull:
op = BrOnCast;
break;
case BinaryConsts::BrOnCastStaticFail:
case BinaryConsts::BrOnCastFail:
- op = BrOnCastFail;
- break;
- case BinaryConsts::BrOnCastNull:
- op = BrOnCast;
- nullability = Nullable;
- break;
case BinaryConsts::BrOnCastFailNull:
op = BrOnCastFail;
- nullability = Nullable;
break;
case BinaryConsts::BrOnFunc:
- op = BrOnFunc;
+ op = BrOnCast;
+ castType = Type(HeapType::func, NonNullable);
break;
case BinaryConsts::BrOnNonFunc:
- op = BrOnNonFunc;
+ op = BrOnCastFail;
+ castType = Type(HeapType::func, NonNullable);
break;
case BinaryConsts::BrOnData:
- op = BrOnData;
+ op = BrOnCast;
+ castType = Type(HeapType::data, NonNullable);
break;
case BinaryConsts::BrOnNonData:
- op = BrOnNonData;
+ op = BrOnCastFail;
+ castType = Type(HeapType::data, NonNullable);
break;
case BinaryConsts::BrOnI31:
- op = BrOnI31;
+ op = BrOnCast;
+ castType = Type(HeapType::i31, NonNullable);
break;
case BinaryConsts::BrOnNonI31:
- op = BrOnNonI31;
+ op = BrOnCastFail;
+ castType = Type(HeapType::i31, NonNullable);
break;
default:
return false;
}
auto name = getBreakTarget(getU32LEB()).name;
- Type castType = Type::none;
- if (op == BrOnCast || op == BrOnCastFail) {
+ if (castType == Type::none && (op == BrOnCast || op == BrOnCastFail)) {
+ auto nullability = (code == BinaryConsts::BrOnCastNull ||
+ code == BinaryConsts::BrOnCastFailNull)
+ ? Nullable
+ : NonNullable;
bool legacy = code == BinaryConsts::BrOnCastStatic ||
code == BinaryConsts::BrOnCastStaticFail;
auto type = legacy ? getIndexedHeapType() : getHeapType();
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index fd3cbcc23..638dfbebf 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2818,11 +2818,20 @@ Expression* SExpressionWasmBuilder::makeRefCastNop(Element& s) {
return Builder(wasm).makeRefCast(ref, type, RefCast::Unsafe);
}
-Expression* SExpressionWasmBuilder::makeBrOn(Element& s, BrOnOp op) {
+Expression* SExpressionWasmBuilder::makeBrOnNull(Element& s, bool onFail) {
int i = 1;
auto name = getLabel(*s[i++]);
- Type castType = Type::none;
- if (op == BrOnCast || op == BrOnCastFail) {
+ auto* ref = parseExpression(*s[i]);
+ auto op = onFail ? BrOnNonNull : BrOnNull;
+ return Builder(wasm).makeBrOn(op, name, ref);
+}
+
+Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s,
+ std::optional<Type> castType,
+ bool onFail) {
+ int i = 1;
+ auto name = getLabel(*s[i++]);
+ if (!castType) {
auto nullability = NonNullable;
if (s[i]->str().str == "null") {
nullability = Nullable;
@@ -2832,7 +2841,8 @@ Expression* SExpressionWasmBuilder::makeBrOn(Element& s, BrOnOp op) {
castType = Type(type, nullability);
}
auto* ref = parseExpression(*s[i]);
- return Builder(wasm).makeBrOn(op, name, ref, castType);
+ auto op = onFail ? BrOnCastFail : BrOnCast;
+ return Builder(wasm).makeBrOn(op, name, ref, *castType);
}
Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) {
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index fbf73b7c2..24710f206 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2052,51 +2052,74 @@ void BinaryInstWriter::visitBrOn(BrOn* curr) {
switch (curr->op) {
case BrOnNull:
o << int8_t(BinaryConsts::BrOnNull);
- break;
+ o << U32LEB(getBreakIndex(curr->name));
+ return;
case BrOnNonNull:
o << int8_t(BinaryConsts::BrOnNonNull);
- break;
+ o << U32LEB(getBreakIndex(curr->name));
+ return;
case BrOnCast:
o << int8_t(BinaryConsts::GCPrefix);
+ // TODO: These instructions are deprecated, so stop emitting them.
+ if (auto type = curr->castType.getHeapType();
+ type.isBasic() && curr->castType.isNonNullable()) {
+ switch (type.getBasic()) {
+ case HeapType::func:
+ o << U32LEB(BinaryConsts::BrOnFunc);
+ o << U32LEB(getBreakIndex(curr->name));
+ return;
+ case HeapType::data:
+ o << U32LEB(BinaryConsts::BrOnData);
+ o << U32LEB(getBreakIndex(curr->name));
+ return;
+ case HeapType::i31:
+ o << U32LEB(BinaryConsts::BrOnI31);
+ o << U32LEB(getBreakIndex(curr->name));
+ return;
+ default:
+ break;
+ }
+ }
if (curr->castType.isNullable()) {
o << U32LEB(BinaryConsts::BrOnCastNull);
} else {
o << U32LEB(BinaryConsts::BrOnCast);
}
- break;
+ o << U32LEB(getBreakIndex(curr->name));
+ parent.writeHeapType(curr->castType.getHeapType());
+ return;
case BrOnCastFail:
o << int8_t(BinaryConsts::GCPrefix);
+ // TODO: These instructions are deprecated, so stop emitting them.
+ if (auto type = curr->castType.getHeapType();
+ type.isBasic() && curr->castType.isNonNullable()) {
+ switch (type.getBasic()) {
+ case HeapType::func:
+ o << U32LEB(BinaryConsts::BrOnNonFunc);
+ o << U32LEB(getBreakIndex(curr->name));
+ return;
+ case HeapType::data:
+ o << U32LEB(BinaryConsts::BrOnNonData);
+ o << U32LEB(getBreakIndex(curr->name));
+ return;
+ case HeapType::i31:
+ o << U32LEB(BinaryConsts::BrOnNonI31);
+ o << U32LEB(getBreakIndex(curr->name));
+ return;
+ default:
+ break;
+ }
+ }
if (curr->castType.isNullable()) {
o << U32LEB(BinaryConsts::BrOnCastFailNull);
} else {
o << U32LEB(BinaryConsts::BrOnCastFail);
}
- break;
- case BrOnFunc:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnFunc);
- break;
- case BrOnNonFunc:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnNonFunc);
- break;
- case BrOnData:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnData);
- break;
- case BrOnNonData:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnNonData);
- break;
- case BrOnI31:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnI31);
- break;
- case BrOnNonI31:
- o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnNonI31);
- break;
- default:
- WASM_UNREACHABLE("invalid br_on_*");
- }
- o << U32LEB(getBreakIndex(curr->name));
- if (curr->op == BrOnCast || curr->op == BrOnCastFail) {
- parent.writeHeapType(curr->castType.getHeapType());
+ o << U32LEB(getBreakIndex(curr->name));
+ parent.writeHeapType(curr->castType.getHeapType());
+ return;
}
+ WASM_UNREACHABLE("invalid br_on_*");
}
void BinaryInstWriter::visitStructNew(StructNew* curr) {
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index de18966ff..c6779a328 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -968,21 +968,6 @@ void BrOn::finalize() {
// us flow out the null, but it does not).
type = Type::none;
break;
- case BrOnFunc:
- case BrOnData:
- case BrOnI31:
- // If we do not branch, we return the input in this case.
- type = ref->type;
- break;
- case BrOnNonFunc:
- type = Type(HeapType::func, NonNullable);
- break;
- case BrOnNonData:
- type = Type(HeapType::data, NonNullable);
- break;
- case BrOnNonI31:
- type = Type(HeapType::i31, NonNullable);
- break;
case BrOnCast:
if (castType.isNullable()) {
// Nulls take the branch, so the result is non-nullable.
@@ -1021,16 +1006,6 @@ Type BrOn::getSentType() {
}
// BrOnNonNull sends the non-nullable type on the branch.
return Type(ref->type.getHeapType(), NonNullable);
- case BrOnFunc:
- return Type(HeapType::func, NonNullable);
- case BrOnData:
- return Type(HeapType::data, NonNullable);
- case BrOnI31:
- return Type(HeapType::i31, NonNullable);
- case BrOnNonFunc:
- case BrOnNonData:
- case BrOnNonI31:
- return ref->type;
case BrOnCast:
// The same as the result type of br_on_cast_fail.
if (castType.isNullable()) {
diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp
index 409d51052..14d30db1c 100644
--- a/src/wasm/wat-parser.cpp
+++ b/src/wasm/wat-parser.cpp
@@ -2349,9 +2349,10 @@ template<typename Ctx> Result<typename Ctx::InstrT> makeRefTest(Ctx&, Index);
template<typename Ctx> Result<typename Ctx::InstrT> makeRefCast(Ctx&, Index);
template<typename Ctx> Result<typename Ctx::InstrT> makeRefCastNop(Ctx&, Index);
template<typename Ctx>
-Result<typename Ctx::InstrT> makeBrOn(Ctx&, Index, BrOnOp op);
+Result<typename Ctx::InstrT> makeBrOnNull(Ctx&, Index, bool onFail = false);
template<typename Ctx>
-Result<typename Ctx::InstrT> makeBrOn(Ctx&, Index, BrOnOp op);
+Result<typename Ctx::InstrT>
+makeBrOnCast(Ctx&, Index, std::optional<Type>, bool onFail = false);
template<typename Ctx>
Result<typename Ctx::InstrT> makeStructNew(Ctx&, Index, bool default_);
template<typename Ctx>
@@ -3452,7 +3453,13 @@ Result<typename Ctx::InstrT> makeRefCastNop(Ctx& ctx, Index pos) {
}
template<typename Ctx>
-Result<typename Ctx::InstrT> makeBrOn(Ctx& ctx, Index pos, BrOnOp op) {
+Result<typename Ctx::InstrT> makeBrOnNull(Ctx& ctx, Index pos, bool onFail) {
+ return ctx.in.err("unimplemented instruction");
+}
+
+template<typename Ctx>
+Result<typename Ctx::InstrT>
+makeBrOnCast(Ctx& ctx, Index pos, std::optional<Type> castType, bool onFail) {
return ctx.in.err("unimplemented instruction");
}