diff options
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 50 | ||||
-rw-r--r-- | test/lit/array-new-fixed.wast | 36 | ||||
-rw-r--r-- | test/lit/if-then-else.wast | 48 | ||||
-rw-r--r-- | test/lit/ref_cast_test.wast | 173 |
4 files changed, 294 insertions, 13 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 4fa4981e4..1f215135e 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1680,7 +1680,7 @@ Expression* SExpressionWasmBuilder::makeBlock(Element& s) { Expression* SExpressionWasmBuilder::makeThenOrElse(Element& s) { auto ret = allocator.alloc<Block>(); size_t i = 1; - if (s[1]->isStr()) { + if (s.size() > 1 && s[1]->isStr()) { i++; } for (; i < s.size(); i++) { @@ -2850,26 +2850,42 @@ Expression* SExpressionWasmBuilder::makeI31Get(Element& s, bool signed_) { Expression* SExpressionWasmBuilder::makeRefTest(Element& s) { int i = 1; - auto nullability = NonNullable; - if (s[1]->str().str == "null") { - nullability = Nullable; - ++i; + Type castType; + if (s[i]->isList() || + !(s[i]->dollared() || + stringToType(s[i]->str(), true /* allowError */) == Type::none)) { + castType = elementToType(*s[i++]); + } else { + // legacy syntax + auto nullability = NonNullable; + if (s[1]->str().str == "null") { + nullability = Nullable; + ++i; + } + auto type = parseHeapType(*s[i++]); + castType = Type(type, nullability); } - auto type = parseHeapType(*s[i++]); - auto castType = Type(type, nullability); auto* ref = parseExpression(*s[i++]); return Builder(wasm).makeRefTest(ref, castType); } Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { int i = 1; - Nullability nullability = NonNullable; - if (s[i]->str().str == "null") { - nullability = Nullable; - ++i; + Type castType; + if (s[i]->isList() || + !(s[i]->dollared() || + stringToType(s[i]->str(), true /* allowError */) == Type::none)) { + castType = elementToType(*s[i++]); + } else { + // legacy syntax + Nullability nullability = NonNullable; + if (s[i]->str().str == "null") { + nullability = Nullable; + ++i; + } + auto type = parseHeapType(*s[i++]); + castType = Type(type, nullability); } - auto type = parseHeapType(*s[i++]); - auto castType = Type(type, nullability); auto* ref = parseExpression(*s[i++]); return Builder(wasm).makeRefCast(ref, castType); } @@ -2990,6 +3006,14 @@ Expression* SExpressionWasmBuilder::makeArrayNewFixed(Element& s) { auto heapType = parseHeapType(*s[1]); size_t i = 2; std::vector<Expression*> values; + if (i < s.size() && s[i]->isStr()) { + // With the standard syntax one should specify explicitly the size + // of the array + if ((size_t)parseIndex(*s[i]) != s.size() - 3) { + throw ParseException("wrong number of elements in array", s.line, s.col); + } + i++; + } while (i < s.size()) { values.push_back(parseExpression(*s[i++])); } diff --git a/test/lit/array-new-fixed.wast b/test/lit/array-new-fixed.wast new file mode 100644 index 000000000..ef20bf5f8 --- /dev/null +++ b/test/lit/array-new-fixed.wast @@ -0,0 +1,36 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; RUN: wasm-opt -all %s -S -o - | filecheck %s + +;; Check that we can optionally specify the size of the array. +(module + ;; CHECK: (type $array (array i32)) + (type $array (array i32)) + ;; CHECK: (func $test (type $none_=>_none) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (array.new_fixed $array + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (array.new_fixed $array + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test + (drop + (array.new_fixed $array + (i32.const 0) + (i32.const 1) + ) + ) + (drop + (array.new_fixed $array 2 + (i32.const 0) + (i32.const 1) + ) + ) + ) +) diff --git a/test/lit/if-then-else.wast b/test/lit/if-then-else.wast new file mode 100644 index 000000000..9d457bef1 --- /dev/null +++ b/test/lit/if-then-else.wast @@ -0,0 +1,48 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; RUN: wasm-opt %s -S -o - | filecheck %s + +;; Check that an empty then or else clause is allowed. +(module + ;; CHECK: (func $test (param $0 i32) (result i32) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (if + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (return + ;; CHECK-NEXT: (i32.const 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (param i32) (result i32) + (if + (local.get $0) + (then) + (else + (return (i32.const 0)) + ) + ) + (if + (local.get $0) + (then + (return + (i32.const 1) + ) + ) + (else) + ) + (return + (i32.const 2) + ) + ) +) diff --git a/test/lit/ref_cast_test.wast b/test/lit/ref_cast_test.wast new file mode 100644 index 000000000..c44278c13 --- /dev/null +++ b/test/lit/ref_cast_test.wast @@ -0,0 +1,173 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; RUN: wasm-opt -all %s -S -o - | filecheck %s + +;; Check that both the legacy and the standard syntax for ref.test and +;; ref.cast work +(module + ;; CHECK: (type $array (array i32)) + (type $array (array i32)) + ;; CHECK: (func $test (type $eqref_=>_none) (param $0 eqref) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast $array + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast null $array + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast i31 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast null i31 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast $array + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast null $array + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast i31 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast null i31 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test $array + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test null $array + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test i31 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test null i31 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test $array + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test null $array + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test i31 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.test null i31 + ;; CHECK-NEXT: (local.get $0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $test (param eqref) + (drop + (ref.cast $array + (local.get 0) + ) + ) + (drop + (ref.cast null $array + (local.get 0) + ) + ) + (drop + (ref.cast i31 + (local.get 0) + ) + ) + (drop + (ref.cast null i31 + (local.get 0) + ) + ) + (drop + (ref.cast (ref $array) + (local.get 0) + ) + ) + (drop + (ref.cast (ref null $array) + (local.get 0) + ) + ) + (drop + (ref.cast (ref i31) + (local.get 0) + ) + ) + (drop + (ref.cast i31ref + (local.get 0) + ) + ) + (drop + (ref.test $array + (local.get 0) + ) + ) + (drop + (ref.test null $array + (local.get 0) + ) + ) + (drop + (ref.test i31 + (local.get 0) + ) + ) + (drop + (ref.test null i31 + (local.get 0) + ) + ) + (drop + (ref.test (ref $array) + (local.get 0) + ) + ) + (drop + (ref.test (ref null $array) + (local.get 0) + ) + ) + (drop + (ref.test (ref i31) + (local.get 0) + ) + ) + (drop + (ref.test i31ref + (local.get 0) + ) + ) + ) +) |