diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 35 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 18 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 79 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 25 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 13 |
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"); } |