diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 30 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 19 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 22 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 21 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 22 |
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_*"); } } |