diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm.h | 1 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 5 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 7 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 17 |
4 files changed, 22 insertions, 8 deletions
diff --git a/src/wasm.h b/src/wasm.h index 39cc9fb54..90628c5bf 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1503,7 +1503,6 @@ public: bool isReturn = false; void finalize(); - void finalize(Type type_); }; class RefTest : public SpecificExpression<Expression::RefTestId> { diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 0d405251e..684afe80c 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -6936,7 +6936,10 @@ void WasmBinaryReader::visitCallRef(CallRef* curr) { for (size_t i = 0; i < num; i++) { curr->operands[num - i - 1] = popNonVoidExpression(); } - curr->finalize(sig.results); + // If the target has bottom type, we won't be able to infer the correct type + // from it, so set the type manually to be safe. + curr->type = sig.results; + curr->finalize(); } bool WasmBinaryReader::maybeVisitI31New(Expression*& out, uint32_t code) { diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 0519afd83..4fa4981e4 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2822,6 +2822,13 @@ Expression* SExpressionWasmBuilder::makeCallRef(Element& s, bool isReturn) { s.line, s.col); } + if (!Type::isSubType(target->type, Type(sigType, Nullable))) { + throw ParseException( + std::string(isReturn ? "return_call_ref" : "call_ref") + + " target should match expected type", + s.line, + s.col); + } return Builder(wasm).makeCallRef( target, operands, sigType.getSignature().results, isReturn); } diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 74b944bb6..188cd2d6f 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -920,18 +920,23 @@ void I31Get::finalize() { } void CallRef::finalize() { - handleUnreachableOperands(this); + if (handleUnreachableOperands(this)) { + return; + } if (isReturn) { type = Type::unreachable; + return; } if (target->type == Type::unreachable) { type = Type::unreachable; + return; } -} - -void CallRef::finalize(Type type_) { - type = type_; - finalize(); + assert(target->type.isRef()); + if (target->type.getHeapType().isBottom()) { + return; + } + assert(target->type.getHeapType().isSignature()); + type = target->type.getHeapType().getSignature().results; } void RefTest::finalize() { |