summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/module-utils.cpp1
-rw-r--r--src/passes/Print.cpp14
-rw-r--r--src/wasm-binary.h12
-rw-r--r--src/wasm/wasm-binary.cpp47
-rw-r--r--src/wasm/wasm-s-parser.cpp14
-rw-r--r--src/wasm/wasm-stack.cpp19
6 files changed, 61 insertions, 46 deletions
diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp
index d3ca1c192..7e202a5da 100644
--- a/src/ir/module-utils.cpp
+++ b/src/ir/module-utils.cpp
@@ -91,6 +91,7 @@ struct CodeScanner
counts.note(cast->castType);
} else if (auto* cast = curr->dynCast<BrOn>()) {
if (cast->op == BrOnCast || cast->op == BrOnCastFail) {
+ counts.note(cast->ref->type);
counts.note(cast->castType);
}
} else if (auto* get = curr->dynCast<StructGet>()) {
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 0d74d43f1..4bcc042a1 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -2172,10 +2172,9 @@ struct PrintExpressionContents
printMedium(o, "br_on_cast ");
printName(curr->name, o);
o << ' ';
- if (curr->castType.isNullable()) {
- printMedium(o, "null ");
- }
- printHeapType(o, curr->castType.getHeapType(), wasm);
+ printType(o, curr->ref->type, wasm);
+ o << ' ';
+ printType(o, curr->castType, wasm);
return;
case BrOnCastFail:
// TODO: These instructions are deprecated, so stop emitting them.
@@ -2197,10 +2196,9 @@ struct PrintExpressionContents
printMedium(o, "br_on_cast_fail ");
printName(curr->name, o);
o << ' ';
- if (curr->castType.isNullable()) {
- printMedium(o, "null ");
- }
- printHeapType(o, curr->castType.getHeapType(), wasm);
+ printType(o, curr->ref->type, wasm);
+ o << ' ';
+ printType(o, curr->castType, wasm);
return;
}
WASM_UNREACHABLE("Unexpected br_on* op");
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index d1b7b4923..81cc80d22 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -1119,16 +1119,16 @@ enum ASTNodes {
I31GetU = 0x22,
RefTest = 0x40,
RefCast = 0x41,
- BrOnCast = 0x42,
- BrOnCastFail = 0x43,
+ BrOnCastLegacy = 0x42,
+ BrOnCastFailLegacy = 0x43,
+ BrOnCastNullLegacy = 0x4a,
+ BrOnCastFailNullLegacy = 0x4b,
+ BrOnCast = 0x4e,
+ BrOnCastFail = 0x4f,
RefTestStatic = 0x44,
RefCastStatic = 0x45,
- BrOnCastStatic = 0x46,
- BrOnCastStaticFail = 0x47,
RefTestNull = 0x48,
RefCastNull = 0x49,
- BrOnCastNull = 0x4a,
- BrOnCastFailNull = 0x4b,
RefCastNop = 0x4c,
RefAsFunc = 0x58,
RefAsI31 = 0x5a,
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 7b3f741b6..ed27dd81a 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -7043,14 +7043,14 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) {
case BinaryConsts::BrOnNonNull:
op = BrOnNonNull;
break;
- case BinaryConsts::BrOnCastStatic:
case BinaryConsts::BrOnCast:
- case BinaryConsts::BrOnCastNull:
+ case BinaryConsts::BrOnCastLegacy:
+ case BinaryConsts::BrOnCastNullLegacy:
op = BrOnCast;
break;
- case BinaryConsts::BrOnCastStaticFail:
case BinaryConsts::BrOnCastFail:
- case BinaryConsts::BrOnCastFailNull:
+ case BinaryConsts::BrOnCastFailLegacy:
+ case BinaryConsts::BrOnCastFailNullLegacy:
op = BrOnCastFail;
break;
case BinaryConsts::BrOnFunc:
@@ -7072,18 +7072,37 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) {
default:
return false;
}
- auto name = getBreakTarget(getU32LEB()).name;
- 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();
- castType = Type(type, nullability);
+ bool hasInputAnnotation =
+ code == BinaryConsts::BrOnCast || code == BinaryConsts::BrOnCastFail;
+ uint8_t flags = 0;
+ if (hasInputAnnotation) {
+ flags = getInt8();
}
+ auto name = getBreakTarget(getU32LEB()).name;
auto* ref = popNonVoidExpression();
+ if (op == BrOnCast || op == BrOnCastFail) {
+ Nullability inputNullability, castNullability;
+ HeapType inputHeapType, castHeapType;
+ if (hasInputAnnotation) {
+ inputNullability = (flags & 1) ? Nullable : NonNullable;
+ castNullability = (flags & 2) ? Nullable : NonNullable;
+ inputHeapType = getHeapType();
+ } else {
+ castNullability = (code == BinaryConsts::BrOnCastNullLegacy ||
+ code == BinaryConsts::BrOnCastFailNullLegacy)
+ ? Nullable
+ : NonNullable;
+ }
+ castHeapType = getHeapType();
+ castType = Type(castHeapType, castNullability);
+ if (hasInputAnnotation) {
+ auto inputType = Type(inputHeapType, inputNullability);
+ if (!Type::isSubType(ref->type, inputType)) {
+ throwError(std::string("Invalid reference type for ") +
+ ((op == BrOnCast) ? "br_on_cast" : "br_on_cast_fail"));
+ }
+ }
+ }
out = Builder(wasm).makeBrOn(op, name, ref, castType);
return true;
}
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 6adfb6149..a51ad3716 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -2892,16 +2892,16 @@ Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s,
bool onFail) {
int i = 1;
auto name = getLabel(*s[i++]);
+ std::optional<Type> inputType;
if (!castType) {
- auto nullability = NonNullable;
- if (s[i]->str().str == "null") {
- nullability = Nullable;
- ++i;
- }
- auto type = parseHeapType(*s[i++]);
- castType = Type(type, nullability);
+ inputType = elementToType(*s[i++]);
+ castType = elementToType(*s[i++]);
}
auto* ref = parseExpression(*s[i]);
+ if (inputType && !Type::isSubType(ref->type, *inputType)) {
+ throw ParseException(
+ "br_on_cast* ref type does not match expected type", s.line, s.col);
+ }
auto op = onFail ? BrOnCastFail : BrOnCast;
return Builder(wasm).makeBrOn(op, name, ref, *castType);
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index 7a4dd3983..ee457da69 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -2045,25 +2045,22 @@ void BinaryInstWriter::visitBrOn(BrOn* curr) {
o << U32LEB(getBreakIndex(curr->name));
return;
case BrOnCast:
+ case BrOnCastFail: {
o << int8_t(BinaryConsts::GCPrefix);
- if (curr->castType.isNullable()) {
- o << U32LEB(BinaryConsts::BrOnCastNull);
- } else {
+ if (curr->op == BrOnCast) {
o << U32LEB(BinaryConsts::BrOnCast);
- }
- o << U32LEB(getBreakIndex(curr->name));
- parent.writeHeapType(curr->castType.getHeapType());
- return;
- case BrOnCastFail:
- o << int8_t(BinaryConsts::GCPrefix);
- if (curr->castType.isNullable()) {
- o << U32LEB(BinaryConsts::BrOnCastFailNull);
} else {
o << U32LEB(BinaryConsts::BrOnCastFail);
}
+ assert(curr->ref->type.isRef());
+ uint8_t flags = (curr->ref->type.isNullable() ? 1 : 0) |
+ (curr->castType.isNullable() ? 2 : 0);
+ o << flags;
o << U32LEB(getBreakIndex(curr->name));
+ parent.writeHeapType(curr->ref->type.getHeapType());
parent.writeHeapType(curr->castType.getHeapType());
return;
+ }
}
WASM_UNREACHABLE("invalid br_on_*");
}