diff options
22 files changed, 161 insertions, 100 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c01e0aa0..51c49eab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,8 @@ Current Trunk - Add extra `memory64` argument for `BinaryenSetMemory` and new `BinaryenMemoryIs64` C-API method to determine 64-bit memory. (#4963) - `TypeBuilderSetSubType` now takes a supertype as the second argument. -- `call_ref` now takes a mandatory signature type immediate. +- `call_ref` can now take a signature type immediate in the text format. The + type immediate will become mandatory in the future. - If `THROW_ON_FATAL` is defined at compile-time, then fatal errors will throw a `std::runtime_error` instead of terminating the process. This may be used by embedders of Binaryen to recover from errors. diff --git a/src/wasm-binary.h b/src/wasm-binary.h index acde624f7..eb8e176ec 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1094,7 +1094,8 @@ enum ASTNodes { // typed function references opcodes - CallRef = 0x14, + CallRefUnannotated = 0x14, + CallRef = 0x17, RetCallRef = 0x15, // gc opcodes @@ -1742,7 +1743,8 @@ public: void visitTryOrTryInBlock(Expression*& out); void visitThrow(Throw* curr); void visitRethrow(Rethrow* curr); - void visitCallRef(CallRef* curr); + void visitCallRef(CallRef* curr, + std::optional<HeapType> maybeType = std::nullopt); void visitRefAs(RefAs* curr, uint8_t code); [[noreturn]] void throwError(std::string text); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index a29867e55..1eb31157d 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -1342,6 +1342,35 @@ public: } return makeBrOn(op, name, ref); } + + template<typename T> + Expression* validateAndMakeCallRef(Expression* target, + const T& args, + bool isReturn = false) { + if (target->type != Type::unreachable && !target->type.isRef()) { + throw ParseException("Non-reference type for a call_ref", line, col); + } + // TODO: This won't be necessary once type annotations are mandatory on + // call_ref. + if (target->type == Type::unreachable || + target->type.getHeapType() == HeapType::nofunc) { + // An unreachable target is not supported. Similiar to br_on_cast, just + // emit an unreachable sequence, since we don't have enough information + // to create a full call_ref. + std::vector<Expression*> children; + for (auto* arg : args) { + children.push_back(makeDrop(arg)); + } + children.push_back(makeDrop(target)); + children.push_back(makeUnreachable()); + return makeBlock(children, Type::unreachable); + } + auto heapType = target->type.getHeapType(); + if (!heapType.isSignature()) { + throw ParseException("Invalid reference type for a call_ref", line, col); + } + return makeCallRef(target, args, heapType.getSignature().results, isReturn); + } }; } // namespace wasm diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 782979520..e2bb0075b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -3846,12 +3846,15 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { visitMemoryGrow(grow); break; } + case BinaryConsts::CallRefUnannotated: + visitCallRef((curr = allocator.alloc<CallRef>())->cast<CallRef>()); + break; case BinaryConsts::CallRef: case BinaryConsts::RetCallRef: { auto call = allocator.alloc<CallRef>(); call->isReturn = code == BinaryConsts::RetCallRef; curr = call; - visitCallRef(call); + visitCallRef(call, getTypeByIndex(getU32LEB())); break; } case BinaryConsts::AtomicPrefix: { @@ -6848,13 +6851,29 @@ void WasmBinaryBuilder::visitRethrow(Rethrow* curr) { curr->finalize(); } -void WasmBinaryBuilder::visitCallRef(CallRef* curr) { +void WasmBinaryBuilder::visitCallRef(CallRef* curr, + std::optional<HeapType> maybeType) { BYN_TRACE("zz node: CallRef\n"); curr->target = popNonVoidExpression(); - HeapType heapType = getTypeByIndex(getU32LEB()); - if (!Type::isSubType(curr->target->type, Type(heapType, Nullable))) { - throwError("Call target has invalid type: " + - curr->target->type.toString()); + HeapType heapType; + if (maybeType) { + heapType = *maybeType; + if (!Type::isSubType(curr->target->type, Type(heapType, Nullable))) { + throwError("Call target has invalid type: " + + curr->target->type.toString()); + } + } else { + auto type = curr->target->type; + if (type == Type::unreachable) { + // If our input is unreachable, then we cannot even find out how many + // inputs we have, and just set ourselves to unreachable as well. + curr->finalize(type); + return; + } + if (!type.isRef()) { + throwError("Non-ref type for a call_ref: " + type.toString()); + } + heapType = type.getHeapType(); } if (!heapType.isSignature()) { throwError("Invalid reference type for a call_ref: " + heapType.toString()); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index ab6230442..a9fd2de77 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2744,20 +2744,35 @@ Expression* SExpressionWasmBuilder::makeTupleExtract(Element& s) { } Expression* SExpressionWasmBuilder::makeCallRef(Element& s, bool isReturn) { - HeapType sigType = parseHeapType(*s[1]); + Index operandsStart = 1; + std::optional<HeapType> sigType; + try { + sigType = parseHeapType(*s[1]); + operandsStart = 2; + } catch (ParseException& p) { + // The type annotation is required for return_call_ref but temporarily + // optional for call_ref. + if (isReturn) { + throw; + } + } std::vector<Expression*> operands; - parseOperands(s, 2, s.size() - 1, operands); + parseOperands(s, operandsStart, s.size() - 1, operands); auto* target = parseExpression(s[s.size() - 1]); - if (!sigType.isSignature()) { - throw ParseException( - std::string(isReturn ? "return_call_ref" : "call_ref") + - " type annotation should be a signature", - s.line, - s.col); + if (sigType) { + if (!sigType->isSignature()) { + throw ParseException( + std::string(isReturn ? "return_call_ref" : "call_ref") + + " type annotation should be a signature", + s.line, + s.col); + } + return Builder(wasm).makeCallRef( + target, operands, sigType->getSignature().results, isReturn); } - return Builder(wasm).makeCallRef( - target, operands, sigType.getSignature().results, isReturn); + return ValidatingBuilder(wasm, s.line, s.col) + .validateAndMakeCallRef(target, operands, isReturn); } Expression* SExpressionWasmBuilder::makeI31New(Element& s) { diff --git a/test/lit/passes/dae_all-features.wast b/test/lit/passes/dae_all-features.wast index 4ca052835..4e0480ace 100644 --- a/test/lit/passes/dae_all-features.wast +++ b/test/lit/passes/dae_all-features.wast @@ -510,7 +510,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $1 - (call_ref $i64 + (call_ref (i64.const 0) (global.get $global$0) ) diff --git a/test/lit/passes/gufa-refs.wast b/test/lit/passes/gufa-refs.wast index 310bef59b..18c6940cc 100644 --- a/test/lit/passes/gufa-refs.wast +++ b/test/lit/passes/gufa-refs.wast @@ -888,7 +888,7 @@ (local.get $y) ) ;; Send a non-null value only to the second param. - (call_ref $two-params + (call_ref (ref.as_non_null (ref.null $struct) ) @@ -4592,19 +4592,19 @@ ;; Call $i1 twice with the same value, and $i2 twice with different values. ;; Note that structurally the types are identical, but we still ;; differentiate them, allowing us to optimize. - (call_ref $i1 + (call_ref (i32.const 42) (ref.func $reffed1) ) - (call_ref $i1 + (call_ref (i32.const 42) (ref.func $reffed1) ) - (call_ref $i2 + (call_ref (i32.const 1337) (ref.func $reffed2) ) - (call_ref $i2 + (call_ref (i32.const 99999) (ref.func $reffed2) ) diff --git a/test/lit/passes/inlining-optimizing.wast b/test/lit/passes/inlining-optimizing.wast index a7b671f10..65384330a 100644 --- a/test/lit/passes/inlining-optimizing.wast +++ b/test/lit/passes/inlining-optimizing.wast @@ -32,7 +32,7 @@ ;; unreachable.) (call $0) (drop - (call_ref $none_=>_i32 + (call_ref (ref.cast_static $none_=>_i32 (ref.func $0) ) diff --git a/test/lit/passes/local-cse_all-features.wast b/test/lit/passes/local-cse_all-features.wast index 22b6b1903..d901d2d99 100644 --- a/test/lit/passes/local-cse_all-features.wast +++ b/test/lit/passes/local-cse_all-features.wast @@ -4,8 +4,7 @@ ;; RUN: foreach %s %t wasm-opt --local-cse --all-features -S -o - | filecheck %s (module - ;; CHECK: (type $f (func (param i32) (result i32))) - (type $f (func (param i32) (result i32))) + ;; CHECK: (type $i32_=>_i32 (func (param i32) (result i32))) ;; CHECK: (type $none_=>_none (func)) @@ -13,13 +12,13 @@ ;; CHECK: (func $calls (param $x i32) (result i32) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_ref $f + ;; CHECK-NEXT: (call_ref $i32_=>_i32 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (ref.func $calls) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (call_ref $f + ;; CHECK-NEXT: (call_ref $i32_=>_i32 ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: (ref.func $calls) ;; CHECK-NEXT: ) @@ -29,10 +28,10 @@ (func $calls (param $x i32) (result i32) ;; The side effects of calls prevent optimization. (drop - (call_ref $f (i32.const 10) (ref.func $calls)) + (call_ref (i32.const 10) (ref.func $calls)) ) (drop - (call_ref $f (i32.const 10) (ref.func $calls)) + (call_ref (i32.const 10) (ref.func $calls)) ) (i32.const 20) ) diff --git a/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast b/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast index e59c09307..9718b4131 100644 --- a/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast +++ b/test/lit/passes/optimize-instructions-call_ref-roundtrip.wast @@ -69,17 +69,17 @@ (func $call-table-get (param $x i32) ;; The heap type of the call_indirects that we emit here should be the ;; identical one as on the table that they correspond to. - (call_ref $v1 + (call_ref (table.get $table-1 (local.get $x) ) ) - (call_ref $v2 + (call_ref (table.get $table-2 (local.get $x) ) ) - (call_ref $v3 + (call_ref (table.get $table-3 (local.get $x) ) diff --git a/test/lit/passes/optimize-instructions-call_ref.wast b/test/lit/passes/optimize-instructions-call_ref.wast index 66e0ee7d8..a82b15542 100644 --- a/test/lit/passes/optimize-instructions-call_ref.wast +++ b/test/lit/passes/optimize-instructions-call_ref.wast @@ -51,7 +51,7 @@ ;; CHECK-NEXT: ) (func $call_ref-to-direct (param $x i32) (param $y i32) ;; This call_ref should become a direct call. - (call_ref $i32_i32_=>_none + (call_ref (local.get $x) (local.get $y) (ref.func $foo) @@ -84,7 +84,7 @@ ;; This call_ref should become a direct call, even though it doesn't have a ;; simple ref.func as the target - we need to look into the fallthrough, and ;; handle things with locals. - (call_ref $i32_i32_=>_none + (call_ref ;; Write to $x before the block, and write to it in the block; we should not ;; reorder these things as the side effects could alter what value appears ;; in the get of $x. (There is a risk of reordering here if we naively moved @@ -116,7 +116,7 @@ (func $fallthrough-no-params (result i32) ;; A fallthrough appears here, but there are no operands so this is easier to ;; optimize: we can just drop the call_ref's target before the call. - (call_ref $none_=>_i32 + (call_ref (block (result (ref $none_=>_i32)) (nop) (ref.func $fallthrough-no-params) @@ -148,7 +148,7 @@ ;; nullable, which means we must be careful when we create a temp local for ;; it: the local should be nullable, and gets of it should use a ;; ref.as_non_null so that we validate. - (call_ref $data_=>_none + (call_ref (local.get $x) (block (result (ref $data_=>_none)) (nop) @@ -174,7 +174,7 @@ ;; emit non-validating code here, which would happen if we replace the ;; call_ref that returns nothing with a call that returns an i32. In fact, we ;; end up optimizing the cast into an unreachable. - (call_ref $none_=>_i32 + (call_ref (ref.cast_static $none_=>_i32 (ref.func $return-nothing) ) @@ -199,7 +199,7 @@ ;; CHECK-NEXT: ) (func $fallthrough-unreachable ;; If the call is not reached, do not optimize it. - (call_ref $i32_i32_=>_none + (call_ref (unreachable) (unreachable) (block (result (ref $i32_i32_=>_none)) @@ -210,16 +210,14 @@ ) ;; CHECK: (func $ignore-unreachable - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) - ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (unreachable) - ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) (func $ignore-unreachable ;; Ignore an unreachable call_ref target entirely. - (call_ref $i32_i32_=>_none + (call_ref (unreachable) ) ) @@ -232,7 +230,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $call-table-get (param $x i32) - (call_ref $i32_i32_=>_none + (call_ref (i32.const 1) (i32.const 2) (table.get $table-1 @@ -275,7 +273,7 @@ ;; CHECK-NEXT: ) (func $call_ref-to-select (param $x i32) (param $y i32) (param $z i32) (param $f (ref $i32_i32_=>_none)) ;; This call_ref should become an if over two direct calls. - (call_ref $i32_i32_=>_none + (call_ref (local.get $x) (local.get $y) (select @@ -286,7 +284,7 @@ ) ;; But here one arm is not constant, so we do not optimize. - (call_ref $i32_i32_=>_none + (call_ref (local.get $x) (local.get $y) (select diff --git a/test/lit/passes/precompute-gc.wast b/test/lit/passes/precompute-gc.wast index 896158637..78e91d749 100644 --- a/test/lit/passes/precompute-gc.wast +++ b/test/lit/passes/precompute-gc.wast @@ -1198,7 +1198,7 @@ (drop ;; Read from the local, checking whether precompute set a value there (it ;; should not, as the cast fails). - (call_ref $func-return-i32 + (call_ref (local.get $temp) ) ) diff --git a/test/lit/passes/remove-unused-module-elements-refs.wast b/test/lit/passes/remove-unused-module-elements-refs.wast index 2c9df16f8..497af29ee 100644 --- a/test/lit/passes/remove-unused-module-elements-refs.wast +++ b/test/lit/passes/remove-unused-module-elements-refs.wast @@ -23,7 +23,7 @@ ;; CHECK-NEXT: (call_ref $A ;; CHECK-NEXT: (local.get $A) ;; CHECK-NEXT: ) - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (unreachable) ;; CHECK-NEXT: ) @@ -38,12 +38,12 @@ (drop (ref.func $target-B) ) - (call_ref $A + (call_ref (local.get $A) ) ;; Verify that we do not crash on an unreachable call_ref, which has no ;; heap type for us to analyze. - (call_ref $A + (call_ref (unreachable) ) ) @@ -85,7 +85,7 @@ ;; CHECK: (export "foo" (func $foo)) ;; CHECK: (func $foo (type $A) - ;; CHECK-NEXT: (block ;; (replaces something unreachable we can't emit) + ;; CHECK-NEXT: (block ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (ref.null nofunc) ;; CHECK-NEXT: ) @@ -96,7 +96,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $foo (export "foo") - (call_ref $A + (call_ref (ref.null $A) ) (drop @@ -143,13 +143,13 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $foo (export "foo") (param $A (ref null $A)) - (call_ref $A + (call_ref (local.get $A) ) (drop (ref.func $target-A-1) ) - (call_ref $A + (call_ref (local.get $A) ) (drop @@ -207,13 +207,13 @@ (drop (ref.func $target-A-1) ) - (call_ref $A + (call_ref (local.get $A) ) (drop (ref.func $target-A-2) ) - (call_ref $A + (call_ref (local.get $A) ) ) diff --git a/test/lit/passes/signature-pruning.wast b/test/lit/passes/signature-pruning.wast index 4b3cfa0c4..26ecadfc9 100644 --- a/test/lit/passes/signature-pruning.wast +++ b/test/lit/passes/signature-pruning.wast @@ -56,7 +56,7 @@ (f32.const 2) (f64.const 3) ) - (call_ref $sig + (call_ref (i32.const 4) (i64.const 5) (f32.const 6) @@ -120,7 +120,7 @@ (f32.const 2) (f64.const 3) ) - (call_ref $sig + (call_ref (i32.const 4) (i64.const 5) (f32.const 6) @@ -194,7 +194,7 @@ (f32.const 2) (f64.const 3) ) - (call_ref $sig + (call_ref (i32.const 4) (i64.const 5) (f32.const 6) @@ -263,7 +263,7 @@ (f32.const 2) (f64.const 3) ) - (call_ref $sig + (call_ref (block (result i32) (call $caller) (i32.const 4) @@ -312,7 +312,7 @@ (f32.const 2) (f64.const 3) ) - (call_ref $sig + (call_ref (i32.const 4) (i64.const 5) (f32.const 6) @@ -515,11 +515,11 @@ (call $bar (i32.const 1) ) - (call_ref $sig + (call_ref (i32.const 2) (ref.func $foo) ) - (call_ref $sig + (call_ref (i32.const 2) (ref.func $bar) ) @@ -536,7 +536,7 @@ (call $bar (i32.const 1) ) - (call_ref $sig + (call_ref (i32.const 2) (ref.func $foo) ) diff --git a/test/lit/passes/signature-refining.wast b/test/lit/passes/signature-refining.wast index 8313a75f9..3d2f7b1a4 100644 --- a/test/lit/passes/signature-refining.wast +++ b/test/lit/passes/signature-refining.wast @@ -60,7 +60,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $caller - (call_ref $sig + (call_ref (struct.new $struct) (ref.func $func) ) @@ -107,7 +107,7 @@ ;; Use a local to avoid a ref.null being updated. (local.get $struct) ) - (call_ref $sig + (call_ref (ref.as_data (struct.new $struct) ) @@ -298,7 +298,7 @@ (call $func (struct.new $struct) ) - (call_ref $sig + (call_ref (unreachable) (ref.func $func) ) @@ -331,7 +331,7 @@ ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $caller - (call_ref $sig + (call_ref (unreachable) (ref.func $func) ) @@ -420,7 +420,7 @@ (struct.new $struct) (struct.new $struct) ) - (call_ref $sig-2 + (call_ref (local.get $i31) (struct.new $struct) (ref.func $func-2) @@ -573,7 +573,7 @@ (drop (if (result anyref) (i32.const 1) - (call_ref $sig-can-refine + (call_ref (ref.func $func-can-refine) ) (unreachable) diff --git a/test/lit/types-function-references.wast b/test/lit/types-function-references.wast index d51b73a84..8722ff3fd 100644 --- a/test/lit/types-function-references.wast +++ b/test/lit/types-function-references.wast @@ -74,7 +74,7 @@ ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) (func $call-ref - (call_ref $void (ref.func $call-ref)) + (call_ref (ref.func $call-ref)) ) ;; CHECK-BINARY: (func $return-call-ref ;; CHECK-BINARY-NEXT: (return_call_ref $void @@ -102,7 +102,7 @@ ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) (func $call-ref-more (param i32) (result i32) - (call_ref $i32-i32 (i32.const 42) (ref.func $call-ref-more)) + (call_ref (i32.const 42) (ref.func $call-ref-more)) ) ;; CHECK-BINARY: (func $call_from-param (param $f (ref $i32-i32)) (result i32) ;; CHECK-BINARY-NEXT: (call_ref $i32-i32 @@ -117,7 +117,7 @@ ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) (func $call_from-param (param $f (ref $i32-i32)) (result i32) - (call_ref $i32-i32 (i32.const 42) (local.get $f)) + (call_ref (i32.const 42) (local.get $f)) ) ;; CHECK-BINARY: (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) ;; CHECK-BINARY-NEXT: (call_ref $i32-i32 @@ -132,7 +132,7 @@ ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) (func $call_from-param-null (param $f (ref null $i32-i32)) (result i32) - (call_ref $i32-i32 (i32.const 42) (local.get $f)) + (call_ref (i32.const 42) (local.get $f)) ) ;; CHECK-BINARY: (func $call_from-local-null (result i32) ;; CHECK-BINARY-NEXT: (local $f (ref null $i32-i32)) @@ -157,7 +157,7 @@ (func $call_from-local-null (result i32) (local $f (ref null $i32-i32)) (local.set $f (ref.func $call-ref-more)) - (call_ref $i32-i32 (i32.const 42) (local.get $f)) + (call_ref (i32.const 42) (local.get $f)) ) ;; CHECK-BINARY: (func $ref-in-sig (param $0 f64) (result (ref null $=>eqref)) ;; CHECK-BINARY-NEXT: (ref.null nofunc) diff --git a/test/lit/validation/nn-locals-bad-call_ref.wast b/test/lit/validation/nn-locals-bad-call_ref.wast index 9a96ed4bc..357409eef 100644 --- a/test/lit/validation/nn-locals-bad-call_ref.wast +++ b/test/lit/validation/nn-locals-bad-call_ref.wast @@ -6,12 +6,11 @@ (module (tag $tag (param i32)) - (type $void (func)) (func $func (local $0 (ref any)) (try (do - (call_ref $void + (call_ref (ref.func $func) ) ) diff --git a/test/passes/Oz_fuzz-exec_all-features.wast b/test/passes/Oz_fuzz-exec_all-features.wast index 94bc2aa3c..a07e7e3d7 100644 --- a/test/passes/Oz_fuzz-exec_all-features.wast +++ b/test/passes/Oz_fuzz-exec_all-features.wast @@ -275,12 +275,12 @@ (func "cast-on-func" (call $log (i32.const 0)) ;; a valid cast - (call_ref $void_func + (call_ref (ref.cast_static $void_func (ref.func $a-void-func)) ) (call $log (i32.const 1)) ;; an invalid cast - (drop (call_ref $int_func + (drop (call_ref (ref.cast_static $int_func (ref.func $a-void-func)) )) ;; will never be reached diff --git a/test/passes/duplicate-function-elimination_all-features.wast b/test/passes/duplicate-function-elimination_all-features.wast index df8d26b6f..1d04e878c 100644 --- a/test/passes/duplicate-function-elimination_all-features.wast +++ b/test/passes/duplicate-function-elimination_all-features.wast @@ -34,7 +34,7 @@ (unreachable) ) (func "export" (result i32) - (call_ref $func + (call_ref (global.get $global$0) ) ) diff --git a/test/spec/br_on_null.wast b/test/spec/br_on_null.wast index e3c45ece7..8e0a8591f 100644 --- a/test/spec/br_on_null.wast +++ b/test/spec/br_on_null.wast @@ -3,13 +3,13 @@ (func $nn (param $r (ref $t)) (result i32) (block $l - (return (call_ref $t (br_on_null $l (local.get $r)))) + (return (call_ref (br_on_null $l (local.get $r)))) ) (i32.const -1) ) (func $n (param $r (ref null $t)) (result i32) (block $l - (return (call_ref $t (br_on_null $l (local.get $r)))) + (return (call_ref (br_on_null $l (local.get $r)))) ) (i32.const -1) ) @@ -22,7 +22,7 @@ (func (export "unreachable") (result i32) (block $l - (return (call_ref $t (br_on_null $l (unreachable)))) + (return (call_ref (br_on_null $l (unreachable)))) ) (i32.const -1) ) @@ -49,7 +49,7 @@ (func $nn (param $r (ref $t)) (result i32) (block $l (ref null $t) ;; br_on_null sends no value; a br to here is bad - (return (call_ref $t (br_on_null $l (local.get $r)))) + (return (call_ref (br_on_null $l (local.get $r)))) ) (i32.const -1) ) diff --git a/test/spec/call_ref.wast b/test/spec/call_ref.wast index 071aa8bbf..8a34706f2 100644 --- a/test/spec/call_ref.wast +++ b/test/spec/call_ref.wast @@ -2,7 +2,7 @@ (type $ii (func (param i32) (result i32))) (func $apply (param $f (ref $ii)) (param $x i32) (result i32) - (call_ref $ii (local.get $x) (local.get $f)) + (call_ref (local.get $x) (local.get $f)) ) (func $f (type $ii) (i32.mul (local.get 0) (local.get 0))) @@ -15,11 +15,11 @@ (local $rg (ref null $ii)) (local.set $rf (ref.func $f)) (local.set $rg (ref.func $g)) - (call_ref $ii (call_ref $ii (local.get $x) (local.get $rf)) (local.get $rg)) + (call_ref (call_ref (local.get $x) (local.get $rf)) (local.get $rg)) ) (func (export "null") (result i32) - (call_ref $ii (i32.const 1) (ref.null $ii)) + (call_ref (i32.const 1) (ref.null $ii)) ) ;; Recursion @@ -36,7 +36,7 @@ (else (i64.mul (local.get 0) - (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $fac)) + (call_ref (i64.sub (local.get 0) (i64.const 1)) (global.get $fac)) ) ) ) @@ -49,7 +49,7 @@ (if (result i64) (i64.eqz (local.get 0)) (then (local.get 1)) (else - (call_ref $lll + (call_ref (i64.sub (local.get 0) (i64.const 1)) (i64.mul (local.get 0) (local.get 1)) (global.get $fac-acc) @@ -66,8 +66,8 @@ (then (i64.const 1)) (else (i64.add - (call_ref $ll (i64.sub (local.get 0) (i64.const 2)) (global.get $fib)) - (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $fib)) + (call_ref (i64.sub (local.get 0) (i64.const 2)) (global.get $fib)) + (call_ref (i64.sub (local.get 0) (i64.const 1)) (global.get $fib)) ) ) ) @@ -80,13 +80,13 @@ (func $even (export "even") (type $ll) (if (result i64) (i64.eqz (local.get 0)) (then (i64.const 44)) - (else (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $odd))) + (else (call_ref (i64.sub (local.get 0) (i64.const 1)) (global.get $odd))) ) ) (func $odd (export "odd") (type $ll) (if (result i64) (i64.eqz (local.get 0)) (then (i64.const 99)) - (else (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $even))) + (else (call_ref (i64.sub (local.get 0) (i64.const 1)) (global.get $even))) ) ) ) @@ -127,9 +127,8 @@ (assert_invalid (module - (type $t (func)) (func $f (param $r externref) - (call_ref $t (local.get $r)) + (call_ref (local.get $r)) ) ) "type mismatch" diff --git a/test/spec/ref_as_non_null.wast b/test/spec/ref_as_non_null.wast index e597e7b9b..7e9417191 100644 --- a/test/spec/ref_as_non_null.wast +++ b/test/spec/ref_as_non_null.wast @@ -2,10 +2,10 @@ (type $t (func (result i32))) (func $nn (param $r (ref $t)) (result i32) - (call_ref $t (ref.as_non_null (local.get $r))) + (call_ref (ref.as_non_null (local.get $r))) ) (func $n (param $r (ref null $t)) (result i32) - (call_ref $t (ref.as_non_null (local.get $r))) + (call_ref (ref.as_non_null (local.get $r))) ) (elem func $f) |