summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wasm-s-parser.cpp50
-rw-r--r--test/lit/array-new-fixed.wast36
-rw-r--r--test/lit/if-then-else.wast48
-rw-r--r--test/lit/ref_cast_test.wast173
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)
+ )
+ )
+ )
+)