summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2018-11-19 13:31:47 -0800
committerGitHub <noreply@github.com>2018-11-19 13:31:47 -0800
commit7011e47ff4ef1a48d15d399f4dfaa761de4779af (patch)
treea6da8ea3b3416cc5210c5b9edcee64615405f48e
parentfa0dfb6a3da3d05e01051a72d9348b2f3024222b (diff)
downloadbinaryen-7011e47ff4ef1a48d15d399f4dfaa761de4779af.tar.gz
binaryen-7011e47ff4ef1a48d15d399f4dfaa761de4779af.tar.bz2
binaryen-7011e47ff4ef1a48d15d399f4dfaa761de4779af.zip
Generate sexp instruction parser (#1754)
Also fix broken tests surfaced by the new parser.
-rw-r--r--.flake87
-rw-r--r--.travis.yml6
-rwxr-xr-xscripts/gen-s-parser.py408
-rw-r--r--src/gen-s-parser.inc688
-rw-r--r--src/wasm-s-parser.h6
-rw-r--r--src/wasm/wasm-s-parser.cpp302
-rw-r--r--test/ctor-eval/basics-flatten.wast6
-rw-r--r--test/ctor-eval/basics.wast6
-rw-r--r--test/passes/duplicate-function-elimination_optimize-level=1.wast2
-rw-r--r--test/passes/duplicate-function-elimination_optimize-level=2.wast2
-rw-r--r--test/wasm2js/br_table_temp.wast2
11 files changed, 1134 insertions, 301 deletions
diff --git a/.flake8 b/.flake8
index eb5f86c4c..704b22c34 100644
--- a/.flake8
+++ b/.flake8
@@ -1,3 +1,8 @@
[flake8]
-ignore = E111,E114,E501,E121
+ignore =
+ E111, # indentation not a multiple of 4 (we use 2))
+ E114, # comment indentation not a multiple of 4
+ E501, # line too long
+ E121, # continuation line under-indented for hanging indent
+ E241 # space after comma (ignored for list in gen-s-parser.py)
exclude = ./test/emscripten,./test/spec,./test/wasm-install
diff --git a/.travis.yml b/.travis.yml
index 0ab529690..e36c091e6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,7 +15,9 @@ jobs:
- &test-ubuntu
stage: test
compiler: clang
- python: 2.7
+ python:
+ - 2.7
+ - 3.6
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
@@ -33,6 +35,8 @@ jobs:
script:
- set -o errexit
- flake8
+ # ensure generated parser is up to date
+ - ./scripts/gen-s-parser.py | diff src/gen-s-parser.inc -
- BUILD_SUBDIR=${BUILD_SUBDIR:-.}
- mkdir -p ${BUILD_SUBDIR} && cd ${BUILD_SUBDIR}
- cmake ${TRAVIS_BUILD_DIR} -DCMAKE_C_FLAGS="$COMPILER_FLAGS" -DCMAKE_CXX_FLAGS="$COMPILER_FLAGS" -DCMAKE_INSTALL_PREFIX=install
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py
new file mode 100755
index 000000000..00989ab43
--- /dev/null
+++ b/scripts/gen-s-parser.py
@@ -0,0 +1,408 @@
+#!/usr/bin/env python3
+#
+# Copyright 2018 WebAssembly Community Group participants
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+instructions = [
+ ("unreachable", "makeUnreachable()"),
+ ("nop", "makeNop()"),
+ ("block", "makeBlock(s)"),
+ ("loop", "makeLoop(s)"),
+ ("if", "makeIf(s)"),
+ ("then", "makeThenOrElse(s)"),
+ ("else", "makeThenOrElse(s)"),
+ ("br", "makeBreak(s)"),
+ ("br_if", "makeBreak(s)"),
+ ("br_table", "makeBreakTable(s)"),
+ ("return", "makeReturn(s)"),
+ ("call", "makeCall(s)"),
+ ("call_indirect", "makeCallIndirect(s)"),
+ ("drop", "makeDrop(s)"),
+ ("select", "makeSelect(s)"),
+ ("get_local", "makeGetLocal(s)"),
+ ("set_local", "makeSetLocal(s)"),
+ ("tee_local", "makeTeeLocal(s)"),
+ ("get_global", "makeGetGlobal(s)"),
+ ("set_global", "makeSetGlobal(s)"),
+ ("i32.load", "makeLoad(s, i32, /*isAtomic=*/false)"),
+ ("i64.load", "makeLoad(s, i64, /*isAtomic=*/false)"),
+ ("f32.load", "makeLoad(s, f32, /*isAtomic=*/false)"),
+ ("f64.load", "makeLoad(s, f64, /*isAtomic=*/false)"),
+ ("i32.load8_s", "makeLoad(s, i32, /*isAtomic=*/false)"),
+ ("i32.load8_u", "makeLoad(s, i32, /*isAtomic=*/false)"),
+ ("i32.load16_s", "makeLoad(s, i32, /*isAtomic=*/false)"),
+ ("i32.load16_u", "makeLoad(s, i32, /*isAtomic=*/false)"),
+ ("i64.load8_s", "makeLoad(s, i64, /*isAtomic=*/false)"),
+ ("i64.load8_u", "makeLoad(s, i64, /*isAtomic=*/false)"),
+ ("i64.load16_s", "makeLoad(s, i64, /*isAtomic=*/false)"),
+ ("i64.load16_u", "makeLoad(s, i64, /*isAtomic=*/false)"),
+ ("i64.load32_s", "makeLoad(s, i64, /*isAtomic=*/false)"),
+ ("i64.load32_u", "makeLoad(s, i64, /*isAtomic=*/false)"),
+ ("i32.store", "makeStore(s, i32, /*isAtomic=*/false)"),
+ ("i64.store", "makeStore(s, i64, /*isAtomic=*/false)"),
+ ("f32.store", "makeStore(s, f32, /*isAtomic=*/false)"),
+ ("f64.store", "makeStore(s, f64, /*isAtomic=*/false)"),
+ ("i32.store8", "makeStore(s, i32, /*isAtomic=*/false)"),
+ ("i32.store16", "makeStore(s, i32, /*isAtomic=*/false)"),
+ ("i64.store8", "makeStore(s, i64, /*isAtomic=*/false)"),
+ ("i64.store16", "makeStore(s, i64, /*isAtomic=*/false)"),
+ ("i64.store32", "makeStore(s, i64, /*isAtomic=*/false)"),
+ ("current_memory", "makeHost(s, HostOp::CurrentMemory)"),
+ ("grow_memory", "makeHost(s, HostOp::GrowMemory)"),
+ ("i32.const", "makeConst(s, i32)"),
+ ("i64.const", "makeConst(s, i64)"),
+ ("f32.const", "makeConst(s, f32)"),
+ ("f64.const", "makeConst(s, f64)"),
+ ("i32.eqz", "makeUnary(s, UnaryOp::EqZInt32)"),
+ ("i32.eq", "makeBinary(s, BinaryOp::EqInt32)"),
+ ("i32.ne", "makeBinary(s, BinaryOp::NeInt32)"),
+ ("i32.lt_s", "makeBinary(s, BinaryOp::LtSInt32)"),
+ ("i32.lt_u", "makeBinary(s, BinaryOp::LtUInt32)"),
+ ("i32.gt_s", "makeBinary(s, BinaryOp::GtSInt32)"),
+ ("i32.gt_u", "makeBinary(s, BinaryOp::GtUInt32)"),
+ ("i32.le_s", "makeBinary(s, BinaryOp::LeSInt32)"),
+ ("i32.le_u", "makeBinary(s, BinaryOp::LeUInt32)"),
+ ("i32.ge_s", "makeBinary(s, BinaryOp::GeSInt32)"),
+ ("i32.ge_u", "makeBinary(s, BinaryOp::GeUInt32)"),
+ ("i64.eqz", "makeUnary(s, UnaryOp::EqZInt64)"),
+ ("i64.eq", "makeBinary(s, BinaryOp::EqInt64)"),
+ ("i64.ne", "makeBinary(s, BinaryOp::NeInt64)"),
+ ("i64.lt_s", "makeBinary(s, BinaryOp::LtSInt64)"),
+ ("i64.lt_u", "makeBinary(s, BinaryOp::LtUInt64)"),
+ ("i64.gt_s", "makeBinary(s, BinaryOp::GtSInt64)"),
+ ("i64.gt_u", "makeBinary(s, BinaryOp::GtUInt64)"),
+ ("i64.le_s", "makeBinary(s, BinaryOp::LeSInt64)"),
+ ("i64.le_u", "makeBinary(s, BinaryOp::LeUInt64)"),
+ ("i64.ge_s", "makeBinary(s, BinaryOp::GeSInt64)"),
+ ("i64.ge_u", "makeBinary(s, BinaryOp::GeUInt64)"),
+ ("f32.eq", "makeBinary(s, BinaryOp::EqFloat32)"),
+ ("f32.ne", "makeBinary(s, BinaryOp::NeFloat32)"),
+ ("f32.lt", "makeBinary(s, BinaryOp::LtFloat32)"),
+ ("f32.gt", "makeBinary(s, BinaryOp::GtFloat32)"),
+ ("f32.le", "makeBinary(s, BinaryOp::LeFloat32)"),
+ ("f32.ge", "makeBinary(s, BinaryOp::GeFloat32)"),
+ ("f64.eq", "makeBinary(s, BinaryOp::EqFloat64)"),
+ ("f64.ne", "makeBinary(s, BinaryOp::NeFloat64)"),
+ ("f64.lt", "makeBinary(s, BinaryOp::LtFloat64)"),
+ ("f64.gt", "makeBinary(s, BinaryOp::GtFloat64)"),
+ ("f64.le", "makeBinary(s, BinaryOp::LeFloat64)"),
+ ("f64.ge", "makeBinary(s, BinaryOp::GeFloat64)"),
+ ("i32.clz", "makeUnary(s, UnaryOp::ClzInt32)"),
+ ("i32.ctz", "makeUnary(s, UnaryOp::CtzInt32)"),
+ ("i32.popcnt", "makeUnary(s, UnaryOp::PopcntInt32)"),
+ ("i32.add", "makeBinary(s, BinaryOp::AddInt32)"),
+ ("i32.sub", "makeBinary(s, BinaryOp::SubInt32)"),
+ ("i32.mul", "makeBinary(s, BinaryOp::MulInt32)"),
+ ("i32.div_s", "makeBinary(s, BinaryOp::DivSInt32)"),
+ ("i32.div_u", "makeBinary(s, BinaryOp::DivUInt32)"),
+ ("i32.rem_s", "makeBinary(s, BinaryOp::RemSInt32)"),
+ ("i32.rem_u", "makeBinary(s, BinaryOp::RemUInt32)"),
+ ("i32.and", "makeBinary(s, BinaryOp::AndInt32)"),
+ ("i32.or", "makeBinary(s, BinaryOp::OrInt32)"),
+ ("i32.xor", "makeBinary(s, BinaryOp::XorInt32)"),
+ ("i32.shl", "makeBinary(s, BinaryOp::ShlInt32)"),
+ ("i32.shr_s", "makeBinary(s, BinaryOp::ShrSInt32)"),
+ ("i32.shr_u", "makeBinary(s, BinaryOp::ShrUInt32)"),
+ ("i32.rotl", "makeBinary(s, BinaryOp::RotLInt32)"),
+ ("i32.rotr", "makeBinary(s, BinaryOp::RotRInt32)"),
+ ("i64.clz", "makeUnary(s, UnaryOp::ClzInt64)"),
+ ("i64.ctz", "makeUnary(s, UnaryOp::CtzInt64)"),
+ ("i64.popcnt", "makeUnary(s, UnaryOp::PopcntInt64)"),
+ ("i64.add", "makeBinary(s, BinaryOp::AddInt64)"),
+ ("i64.sub", "makeBinary(s, BinaryOp::SubInt64)"),
+ ("i64.mul", "makeBinary(s, BinaryOp::MulInt64)"),
+ ("i64.div_s", "makeBinary(s, BinaryOp::DivSInt64)"),
+ ("i64.div_u", "makeBinary(s, BinaryOp::DivUInt64)"),
+ ("i64.rem_s", "makeBinary(s, BinaryOp::RemSInt64)"),
+ ("i64.rem_u", "makeBinary(s, BinaryOp::RemUInt64)"),
+ ("i64.and", "makeBinary(s, BinaryOp::AndInt64)"),
+ ("i64.or", "makeBinary(s, BinaryOp::OrInt64)"),
+ ("i64.xor", "makeBinary(s, BinaryOp::XorInt64)"),
+ ("i64.shl", "makeBinary(s, BinaryOp::ShlInt64)"),
+ ("i64.shr_s", "makeBinary(s, BinaryOp::ShrSInt64)"),
+ ("i64.shr_u", "makeBinary(s, BinaryOp::ShrUInt64)"),
+ ("i64.rotl", "makeBinary(s, BinaryOp::RotLInt64)"),
+ ("i64.rotr", "makeBinary(s, BinaryOp::RotRInt64)"),
+ ("f32.abs", "makeUnary(s, UnaryOp::AbsFloat32)"),
+ ("f32.neg", "makeUnary(s, UnaryOp::NegFloat32)"),
+ ("f32.ceil", "makeUnary(s, UnaryOp::CeilFloat32)"),
+ ("f32.floor", "makeUnary(s, UnaryOp::FloorFloat32)"),
+ ("f32.trunc", "makeUnary(s, UnaryOp::TruncFloat32)"),
+ ("f32.nearest", "makeUnary(s, UnaryOp::NearestFloat32)"),
+ ("f32.sqrt", "makeUnary(s, UnaryOp::SqrtFloat32)"),
+ ("f32.add", "makeBinary(s, BinaryOp::AddFloat32)"),
+ ("f32.sub", "makeBinary(s, BinaryOp::SubFloat32)"),
+ ("f32.mul", "makeBinary(s, BinaryOp::MulFloat32)"),
+ ("f32.div", "makeBinary(s, BinaryOp::DivFloat32)"),
+ ("f32.min", "makeBinary(s, BinaryOp::MinFloat32)"),
+ ("f32.max", "makeBinary(s, BinaryOp::MaxFloat32)"),
+ ("f32.copysign", "makeBinary(s, BinaryOp::CopySignFloat32)"),
+ ("f64.abs", "makeUnary(s, UnaryOp::AbsFloat64)"),
+ ("f64.neg", "makeUnary(s, UnaryOp::NegFloat64)"),
+ ("f64.ceil", "makeUnary(s, UnaryOp::CeilFloat64)"),
+ ("f64.floor", "makeUnary(s, UnaryOp::FloorFloat64)"),
+ ("f64.trunc", "makeUnary(s, UnaryOp::TruncFloat64)"),
+ ("f64.nearest", "makeUnary(s, UnaryOp::NearestFloat64)"),
+ ("f64.sqrt", "makeUnary(s, UnaryOp::SqrtFloat64)"),
+ ("f64.add", "makeBinary(s, BinaryOp::AddFloat64)"),
+ ("f64.sub", "makeBinary(s, BinaryOp::SubFloat64)"),
+ ("f64.mul", "makeBinary(s, BinaryOp::MulFloat64)"),
+ ("f64.div", "makeBinary(s, BinaryOp::DivFloat64)"),
+ ("f64.min", "makeBinary(s, BinaryOp::MinFloat64)"),
+ ("f64.max", "makeBinary(s, BinaryOp::MaxFloat64)"),
+ ("f64.copysign", "makeBinary(s, BinaryOp::CopySignFloat64)"),
+ ("i32.wrap/i64", "makeUnary(s, UnaryOp::WrapInt64)"),
+ ("i32.trunc_s/f32", "makeUnary(s, UnaryOp::TruncSFloat32ToInt32)"),
+ ("i32.trunc_u/f32", "makeUnary(s, UnaryOp::TruncUFloat32ToInt32)"),
+ ("i32.trunc_s/f64", "makeUnary(s, UnaryOp::TruncSFloat64ToInt32)"),
+ ("i32.trunc_u/f64", "makeUnary(s, UnaryOp::TruncUFloat64ToInt32)"),
+ ("i64.extend_s/i32", "makeUnary(s, UnaryOp::ExtendSInt32)"),
+ ("i64.extend_u/i32", "makeUnary(s, UnaryOp::ExtendUInt32)"),
+ ("i64.trunc_s/f32", "makeUnary(s, UnaryOp::TruncSFloat32ToInt64)"),
+ ("i64.trunc_u/f32", "makeUnary(s, UnaryOp::TruncUFloat32ToInt64)"),
+ ("i64.trunc_s/f64", "makeUnary(s, UnaryOp::TruncSFloat64ToInt64)"),
+ ("i64.trunc_u/f64", "makeUnary(s, UnaryOp::TruncUFloat64ToInt64)"),
+ ("f32.convert_s/i32", "makeUnary(s, UnaryOp::ConvertSInt32ToFloat32)"),
+ ("f32.convert_u/i32", "makeUnary(s, UnaryOp::ConvertUInt32ToFloat32)"),
+ ("f32.convert_s/i64", "makeUnary(s, UnaryOp::ConvertSInt64ToFloat32)"),
+ ("f32.convert_u/i64", "makeUnary(s, UnaryOp::ConvertUInt64ToFloat32)"),
+ ("f32.demote/f64", "makeUnary(s, UnaryOp::DemoteFloat64)"),
+ ("f64.convert_s/i32", "makeUnary(s, UnaryOp::ConvertSInt32ToFloat64)"),
+ ("f64.convert_u/i32", "makeUnary(s, UnaryOp::ConvertUInt32ToFloat64)"),
+ ("f64.convert_s/i64", "makeUnary(s, UnaryOp::ConvertSInt64ToFloat64)"),
+ ("f64.convert_u/i64", "makeUnary(s, UnaryOp::ConvertUInt64ToFloat64)"),
+ ("f64.promote/f32", "makeUnary(s, UnaryOp::PromoteFloat32)"),
+ ("i32.reinterpret/f32", "makeUnary(s, UnaryOp::ReinterpretFloat32)"),
+ ("i64.reinterpret/f64", "makeUnary(s, UnaryOp::ReinterpretFloat64)"),
+ ("f32.reinterpret/i32", "makeUnary(s, UnaryOp::ReinterpretInt32)"),
+ ("f64.reinterpret/i64", "makeUnary(s, UnaryOp::ReinterpretInt64)"),
+ ("i32.extend8_s", "makeUnary(s, UnaryOp::ExtendS8Int32)"),
+ ("i32.extend16_s", "makeUnary(s, UnaryOp::ExtendS16Int32)"),
+ ("i64.extend8_s", "makeUnary(s, UnaryOp::ExtendS8Int64)"),
+ ("i64.extend16_s", "makeUnary(s, UnaryOp::ExtendS16Int64)"),
+ ("i64.extend32_s", "makeUnary(s, UnaryOp::ExtendS32Int64)"),
+ # atomic instructions
+ ("wake", "makeAtomicWake(s)"),
+ ("i32.wait", "makeAtomicWait(s, i32)"),
+ ("i64.wait", "makeAtomicWait(s, i64)"),
+ ("i32.atomic.load8_u", "makeLoad(s, i32, /*isAtomic=*/true)"),
+ ("i32.atomic.load16_u", "makeLoad(s, i32, /*isAtomic=*/true)"),
+ ("i32.atomic.load", "makeLoad(s, i32, /*isAtomic=*/true)"),
+ ("i64.atomic.load8_u", "makeLoad(s, i64, /*isAtomic=*/true)"),
+ ("i64.atomic.load16_u", "makeLoad(s, i64, /*isAtomic=*/true)"),
+ ("i64.atomic.load32_u", "makeLoad(s, i64, /*isAtomic=*/true)"),
+ ("i64.atomic.load", "makeLoad(s, i64, /*isAtomic=*/true)"),
+ ("i32.atomic.store8", "makeStore(s, i32, /*isAtomic=*/true)"),
+ ("i32.atomic.store16", "makeStore(s, i32, /*isAtomic=*/true)"),
+ ("i32.atomic.store", "makeStore(s, i32, /*isAtomic=*/true)"),
+ ("i64.atomic.store8", "makeStore(s, i64, /*isAtomic=*/true)"),
+ ("i64.atomic.store16", "makeStore(s, i64, /*isAtomic=*/true)"),
+ ("i64.atomic.store32", "makeStore(s, i64, /*isAtomic=*/true)"),
+ ("i64.atomic.store", "makeStore(s, i64, /*isAtomic=*/true)"),
+ ("i32.atomic.rmw8_u.add", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw16_u.add", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw.add", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i64.atomic.rmw8_u.add", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw16_u.add", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw32_u.add", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw.add", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i32.atomic.rmw8_u.sub", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw16_u.sub", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw.sub", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i64.atomic.rmw8_u.sub", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw16_u.sub", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw32_u.sub", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw.sub", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i32.atomic.rmw8_u.and", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw16_u.and", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw.and", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i64.atomic.rmw8_u.and", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw16_u.and", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw32_u.and", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw.and", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i32.atomic.rmw8_u.or", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw16_u.or", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw.or", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i64.atomic.rmw8_u.or", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw16_u.or", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw32_u.or", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw.or", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i32.atomic.rmw8_u.xor", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw16_u.xor", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw.xor", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i64.atomic.rmw8_u.xor", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw16_u.xor", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw32_u.xor", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw.xor", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i32.atomic.rmw8_u.xchg", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw16_u.xchg", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw.xchg", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i64.atomic.rmw8_u.xchg", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw16_u.xchg", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw32_u.xchg", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw.xchg", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i32.atomic.rmw8_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw16_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i32.atomic.rmw.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i32)"),
+ ("i64.atomic.rmw8_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw16_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw32_u.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i64)"),
+ ("i64.atomic.rmw.cmpxchg", "makeAtomicRMWOrCmpxchg(s, i64)")
+]
+
+
+class CodePrinter:
+ indents = 0
+
+ def __enter__(self):
+ CodePrinter.indents += 1
+
+ def __exit__(self, *args):
+ CodePrinter.indents -= 1
+
+ def indent(self):
+ # call in a 'with' statement
+ return self
+
+ def print_line(self, line):
+ print(" " * CodePrinter.indents + line)
+
+
+class Node:
+ def __init__(self, expr=None, children=None, inst=None):
+ # the expression to return if this is the string has ended
+ self.expr = expr
+ # map unique strings to children nodes
+ self.children = children if children else {}
+ # full instruction leading to this node
+ self.inst = inst
+
+ def _common_prefix(a, b):
+ """Return the common prefix of two strings."""
+ prefix = []
+ while a and b and a[0] == b[0]:
+ prefix.append(a[0])
+ a = a[1:]
+ b = b[1:]
+ return "".join(prefix)
+
+ def do_insert(self, full_inst, inst, expr):
+ if inst is "":
+ assert self.expr is None, "Repeated instruction"
+ self.expr = expr
+ self.inst = full_inst
+ return
+ # find key with shared prefix
+ prefix, key = "", None
+ for k in self.children:
+ prefix = Node._common_prefix(inst, k)
+ if prefix is not "":
+ key = k
+ break
+ if key is None:
+ # unique prefix, insert and stop
+ self.children[inst] = Node(expr, inst=full_inst)
+ return
+ key_remainder = key[len(prefix):]
+ if key_remainder is not "":
+ # split key and move everything after the prefix to a new node
+ child = self.children.pop(key)
+ self.children[prefix] = Node(children={key_remainder: child})
+ # update key for recursive insert
+ key = prefix
+ # chop off prefix and recurse
+ self.children[key].do_insert(full_inst, inst[len(key):], expr)
+
+ def insert(self, inst, expr):
+ self.do_insert(inst, inst, expr)
+
+ def prune(self):
+ """Deduplicate siblings that would lead to the same expression."""
+ if not self.children:
+ return
+ for child in self.children.values():
+ child.prune()
+ exprs = set(self.expr) if self.expr else set()
+ for child in self.children.values():
+ # only prune if all children are terminal
+ if child.children:
+ return
+ exprs.add(child.expr)
+ if len(exprs) != 1:
+ # children have different expressions, can't prune
+ return
+ # do prune
+ self.expr = exprs.pop()
+ self.inst = " | ".join(sorted(c.inst for c in self.children.values()))
+ self.children = {}
+
+
+def instruction_parser():
+ """Build a trie out of all the instructions, then emit it as C++ code."""
+ trie = Node()
+ inst_length = 0
+ for inst, expr in instructions:
+ inst_length = max(inst_length, len(inst))
+ trie.insert(inst, expr)
+ trie.prune()
+
+ printer = CodePrinter()
+
+ printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1))
+ printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length))
+
+ def emit(node, idx=0):
+ assert node.children
+ printer.print_line("switch (op[{}]) {{".format(idx))
+ with printer.indent():
+ if node.expr:
+ printer.print_line("case '\\0': return {}; // {}".format(node.expr, node.inst))
+ children = sorted(node.children.items(), key=lambda pair: pair[0])
+ for prefix, child in children:
+ if child.children:
+ printer.print_line("case '{}': {{".format(prefix[0]))
+ with printer.indent():
+ emit(child, idx + len(prefix))
+ printer.print_line("}")
+ else:
+ assert child.expr
+ printer.print_line("case '{}': return {}; // {}"
+ .format(prefix[0], child.expr, child.inst))
+ printer.print_line("default: goto parse_error;")
+ printer.print_line("}")
+
+ emit(trie)
+ printer.print_line("parse_error:")
+ with printer.indent():
+ printer.print_line("throw ParseException(std::string(op));")
+
+
+def print_header():
+ print("// DO NOT EDIT! This file generated by scripts/gen-s-parser.py\n")
+
+
+def generate_with_guard(generator, guard):
+ print("#ifdef {}".format(guard))
+ print("#undef {}".format(guard))
+ generator()
+ print("#endif // {}".format(guard))
+
+
+def main():
+ print_header()
+ generate_with_guard(instruction_parser, "INSTRUCTION_PARSER")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc
new file mode 100644
index 000000000..5b50d6091
--- /dev/null
+++ b/src/gen-s-parser.inc
@@ -0,0 +1,688 @@
+// DO NOT EDIT! This file generated by scripts/gen-s-parser.py
+
+#ifdef INSTRUCTION_PARSER
+#undef INSTRUCTION_PARSER
+char op[27] = {'\0'};
+strncpy(op, s[0]->c_str(), 26);
+switch (op[0]) {
+ case 'b': {
+ switch (op[1]) {
+ case 'l': return makeBlock(s); // block
+ case 'r': {
+ switch (op[2]) {
+ case '\0': return makeBreak(s); // br
+ case '_': {
+ switch (op[3]) {
+ case 'i': return makeBreak(s); // br_if
+ case 't': return makeBreakTable(s); // br_table
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[1]) {
+ case 'a': {
+ switch (op[4]) {
+ case '\0': return makeCall(s); // call
+ case '_': return makeCallIndirect(s); // call_indirect
+ default: goto parse_error;
+ }
+ }
+ case 'u': return makeHost(s, HostOp::CurrentMemory); // current_memory
+ default: goto parse_error;
+ }
+ }
+ case 'd': return makeDrop(s); // drop
+ case 'e': return makeThenOrElse(s); // else
+ case 'f': {
+ switch (op[1]) {
+ case '3': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[5]) {
+ case 'b': return makeUnary(s, UnaryOp::AbsFloat32); // f32.abs
+ case 'd': return makeBinary(s, BinaryOp::AddFloat32); // f32.add
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[5]) {
+ case 'e': return makeUnary(s, UnaryOp::CeilFloat32); // f32.ceil
+ case 'o': {
+ switch (op[6]) {
+ case 'n': {
+ switch (op[7]) {
+ case 's': return makeConst(s, f32); // f32.const
+ case 'v': {
+ switch (op[12]) {
+ case 's': {
+ switch (op[15]) {
+ case '3': return makeUnary(s, UnaryOp::ConvertSInt32ToFloat32); // f32.convert_s/i32
+ case '6': return makeUnary(s, UnaryOp::ConvertSInt64ToFloat32); // f32.convert_s/i64
+ default: goto parse_error;
+ }
+ }
+ case 'u': {
+ switch (op[15]) {
+ case '3': return makeUnary(s, UnaryOp::ConvertUInt32ToFloat32); // f32.convert_u/i32
+ case '6': return makeUnary(s, UnaryOp::ConvertUInt64ToFloat32); // f32.convert_u/i64
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p': return makeBinary(s, BinaryOp::CopySignFloat32); // f32.copysign
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'd': {
+ switch (op[5]) {
+ case 'e': return makeUnary(s, UnaryOp::DemoteFloat64); // f32.demote/f64
+ case 'i': return makeBinary(s, BinaryOp::DivFloat32); // f32.div
+ default: goto parse_error;
+ }
+ }
+ case 'e': return makeBinary(s, BinaryOp::EqFloat32); // f32.eq
+ case 'f': return makeUnary(s, UnaryOp::FloorFloat32); // f32.floor
+ case 'g': {
+ switch (op[5]) {
+ case 'e': return makeBinary(s, BinaryOp::GeFloat32); // f32.ge
+ case 't': return makeBinary(s, BinaryOp::GtFloat32); // f32.gt
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[5]) {
+ case 'e': return makeBinary(s, BinaryOp::LeFloat32); // f32.le
+ case 'o': return makeLoad(s, f32, /*isAtomic=*/false); // f32.load
+ case 't': return makeBinary(s, BinaryOp::LtFloat32); // f32.lt
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[5]) {
+ case 'a': return makeBinary(s, BinaryOp::MaxFloat32); // f32.max
+ case 'i': return makeBinary(s, BinaryOp::MinFloat32); // f32.min
+ case 'u': return makeBinary(s, BinaryOp::MulFloat32); // f32.mul
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[6]) {
+ case '\0': return makeBinary(s, BinaryOp::NeFloat32); // f32.ne
+ case 'a': return makeUnary(s, UnaryOp::NearestFloat32); // f32.nearest
+ case 'g': return makeUnary(s, UnaryOp::NegFloat32); // f32.neg
+ default: goto parse_error;
+ }
+ }
+ case 'r': return makeUnary(s, UnaryOp::ReinterpretInt32); // f32.reinterpret/i32
+ case 's': {
+ switch (op[5]) {
+ case 'q': return makeUnary(s, UnaryOp::SqrtFloat32); // f32.sqrt
+ case 't': return makeStore(s, f32, /*isAtomic=*/false); // f32.store
+ case 'u': return makeBinary(s, BinaryOp::SubFloat32); // f32.sub
+ default: goto parse_error;
+ }
+ }
+ case 't': return makeUnary(s, UnaryOp::TruncFloat32); // f32.trunc
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[5]) {
+ case 'b': return makeUnary(s, UnaryOp::AbsFloat64); // f64.abs
+ case 'd': return makeBinary(s, BinaryOp::AddFloat64); // f64.add
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[5]) {
+ case 'e': return makeUnary(s, UnaryOp::CeilFloat64); // f64.ceil
+ case 'o': {
+ switch (op[6]) {
+ case 'n': {
+ switch (op[7]) {
+ case 's': return makeConst(s, f64); // f64.const
+ case 'v': {
+ switch (op[12]) {
+ case 's': {
+ switch (op[15]) {
+ case '3': return makeUnary(s, UnaryOp::ConvertSInt32ToFloat64); // f64.convert_s/i32
+ case '6': return makeUnary(s, UnaryOp::ConvertSInt64ToFloat64); // f64.convert_s/i64
+ default: goto parse_error;
+ }
+ }
+ case 'u': {
+ switch (op[15]) {
+ case '3': return makeUnary(s, UnaryOp::ConvertUInt32ToFloat64); // f64.convert_u/i32
+ case '6': return makeUnary(s, UnaryOp::ConvertUInt64ToFloat64); // f64.convert_u/i64
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'p': return makeBinary(s, BinaryOp::CopySignFloat64); // f64.copysign
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'd': return makeBinary(s, BinaryOp::DivFloat64); // f64.div
+ case 'e': return makeBinary(s, BinaryOp::EqFloat64); // f64.eq
+ case 'f': return makeUnary(s, UnaryOp::FloorFloat64); // f64.floor
+ case 'g': {
+ switch (op[5]) {
+ case 'e': return makeBinary(s, BinaryOp::GeFloat64); // f64.ge
+ case 't': return makeBinary(s, BinaryOp::GtFloat64); // f64.gt
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[5]) {
+ case 'e': return makeBinary(s, BinaryOp::LeFloat64); // f64.le
+ case 'o': return makeLoad(s, f64, /*isAtomic=*/false); // f64.load
+ case 't': return makeBinary(s, BinaryOp::LtFloat64); // f64.lt
+ default: goto parse_error;
+ }
+ }
+ case 'm': {
+ switch (op[5]) {
+ case 'a': return makeBinary(s, BinaryOp::MaxFloat64); // f64.max
+ case 'i': return makeBinary(s, BinaryOp::MinFloat64); // f64.min
+ case 'u': return makeBinary(s, BinaryOp::MulFloat64); // f64.mul
+ default: goto parse_error;
+ }
+ }
+ case 'n': {
+ switch (op[6]) {
+ case '\0': return makeBinary(s, BinaryOp::NeFloat64); // f64.ne
+ case 'a': return makeUnary(s, UnaryOp::NearestFloat64); // f64.nearest
+ case 'g': return makeUnary(s, UnaryOp::NegFloat64); // f64.neg
+ default: goto parse_error;
+ }
+ }
+ case 'p': return makeUnary(s, UnaryOp::PromoteFloat32); // f64.promote/f32
+ case 'r': return makeUnary(s, UnaryOp::ReinterpretInt64); // f64.reinterpret/i64
+ case 's': {
+ switch (op[5]) {
+ case 'q': return makeUnary(s, UnaryOp::SqrtFloat64); // f64.sqrt
+ case 't': return makeStore(s, f64, /*isAtomic=*/false); // f64.store
+ case 'u': return makeBinary(s, BinaryOp::SubFloat64); // f64.sub
+ default: goto parse_error;
+ }
+ }
+ case 't': return makeUnary(s, UnaryOp::TruncFloat64); // f64.trunc
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[1]) {
+ case 'e': {
+ switch (op[4]) {
+ case 'g': return makeGetGlobal(s); // get_global
+ case 'l': return makeGetLocal(s); // get_local
+ default: goto parse_error;
+ }
+ }
+ case 'r': return makeHost(s, HostOp::GrowMemory); // grow_memory
+ default: goto parse_error;
+ }
+ }
+ case 'i': {
+ switch (op[1]) {
+ case '3': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[5]) {
+ case 'd': return makeBinary(s, BinaryOp::AddInt32); // i32.add
+ case 'n': return makeBinary(s, BinaryOp::AndInt32); // i32.and
+ case 't': {
+ switch (op[11]) {
+ case 'l': {
+ switch (op[15]) {
+ case '\0': return makeLoad(s, i32, /*isAtomic=*/true); // i32.atomic.load
+ case '1': return makeLoad(s, i32, /*isAtomic=*/true); // i32.atomic.load16_u
+ case '8': return makeLoad(s, i32, /*isAtomic=*/true); // i32.atomic.load8_u
+ default: goto parse_error;
+ }
+ }
+ case 'r': return makeAtomicRMWOrCmpxchg(s, i32); // i32.atomic.rmw.add | i32.atomic.rmw.and | i32.atomic.rmw.cmpxchg | i32.atomic.rmw.or | i32.atomic.rmw.sub | i32.atomic.rmw.xchg | i32.atomic.rmw.xor | i32.atomic.rmw16_u.add | i32.atomic.rmw16_u.and | i32.atomic.rmw16_u.cmpxchg | i32.atomic.rmw16_u.or | i32.atomic.rmw16_u.sub | i32.atomic.rmw16_u.xchg | i32.atomic.rmw16_u.xor | i32.atomic.rmw8_u.add | i32.atomic.rmw8_u.and | i32.atomic.rmw8_u.cmpxchg | i32.atomic.rmw8_u.or | i32.atomic.rmw8_u.sub | i32.atomic.rmw8_u.xchg | i32.atomic.rmw8_u.xor
+ case 's': {
+ switch (op[16]) {
+ case '\0': return makeStore(s, i32, /*isAtomic=*/true); // i32.atomic.store
+ case '1': return makeStore(s, i32, /*isAtomic=*/true); // i32.atomic.store16
+ case '8': return makeStore(s, i32, /*isAtomic=*/true); // i32.atomic.store8
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[5]) {
+ case 'l': return makeUnary(s, UnaryOp::ClzInt32); // i32.clz
+ case 'o': return makeConst(s, i32); // i32.const
+ case 't': return makeUnary(s, UnaryOp::CtzInt32); // i32.ctz
+ default: goto parse_error;
+ }
+ }
+ case 'd': {
+ switch (op[8]) {
+ case 's': return makeBinary(s, BinaryOp::DivSInt32); // i32.div_s
+ case 'u': return makeBinary(s, BinaryOp::DivUInt32); // i32.div_u
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[5]) {
+ case 'q': {
+ switch (op[6]) {
+ case '\0': return makeBinary(s, BinaryOp::EqInt32); // i32.eq
+ case 'z': return makeUnary(s, UnaryOp::EqZInt32); // i32.eqz
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[10]) {
+ case '1': return makeUnary(s, UnaryOp::ExtendS16Int32); // i32.extend16_s
+ case '8': return makeUnary(s, UnaryOp::ExtendS8Int32); // i32.extend8_s
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[7]) {
+ case 's': return makeBinary(s, BinaryOp::GeSInt32); // i32.ge_s
+ case 'u': return makeBinary(s, BinaryOp::GeUInt32); // i32.ge_u
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[7]) {
+ case 's': return makeBinary(s, BinaryOp::GtSInt32); // i32.gt_s
+ case 'u': return makeBinary(s, BinaryOp::GtUInt32); // i32.gt_u
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[7]) {
+ case 's': return makeBinary(s, BinaryOp::LeSInt32); // i32.le_s
+ case 'u': return makeBinary(s, BinaryOp::LeUInt32); // i32.le_u
+ default: goto parse_error;
+ }
+ }
+ case 'o': {
+ switch (op[8]) {
+ case '\0': return makeLoad(s, i32, /*isAtomic=*/false); // i32.load
+ case '1': return makeLoad(s, i32, /*isAtomic=*/false); // i32.load16_s | i32.load16_u
+ case '8': return makeLoad(s, i32, /*isAtomic=*/false); // i32.load8_s | i32.load8_u
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[7]) {
+ case 's': return makeBinary(s, BinaryOp::LtSInt32); // i32.lt_s
+ case 'u': return makeBinary(s, BinaryOp::LtUInt32); // i32.lt_u
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm': return makeBinary(s, BinaryOp::MulInt32); // i32.mul
+ case 'n': return makeBinary(s, BinaryOp::NeInt32); // i32.ne
+ case 'o': return makeBinary(s, BinaryOp::OrInt32); // i32.or
+ case 'p': return makeUnary(s, UnaryOp::PopcntInt32); // i32.popcnt
+ case 'r': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[6]) {
+ case 'i': return makeUnary(s, UnaryOp::ReinterpretFloat32); // i32.reinterpret/f32
+ case 'm': {
+ switch (op[8]) {
+ case 's': return makeBinary(s, BinaryOp::RemSInt32); // i32.rem_s
+ case 'u': return makeBinary(s, BinaryOp::RemUInt32); // i32.rem_u
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'o': {
+ switch (op[7]) {
+ case 'l': return makeBinary(s, BinaryOp::RotLInt32); // i32.rotl
+ case 'r': return makeBinary(s, BinaryOp::RotRInt32); // i32.rotr
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[5]) {
+ case 'h': {
+ switch (op[6]) {
+ case 'l': return makeBinary(s, BinaryOp::ShlInt32); // i32.shl
+ case 'r': {
+ switch (op[8]) {
+ case 's': return makeBinary(s, BinaryOp::ShrSInt32); // i32.shr_s
+ case 'u': return makeBinary(s, BinaryOp::ShrUInt32); // i32.shr_u
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case '\0': return makeStore(s, i32, /*isAtomic=*/false); // i32.store
+ case '1': return makeStore(s, i32, /*isAtomic=*/false); // i32.store16
+ case '8': return makeStore(s, i32, /*isAtomic=*/false); // i32.store8
+ default: goto parse_error;
+ }
+ }
+ case 'u': return makeBinary(s, BinaryOp::SubInt32); // i32.sub
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[10]) {
+ case 's': {
+ switch (op[13]) {
+ case '3': return makeUnary(s, UnaryOp::TruncSFloat32ToInt32); // i32.trunc_s/f32
+ case '6': return makeUnary(s, UnaryOp::TruncSFloat64ToInt32); // i32.trunc_s/f64
+ default: goto parse_error;
+ }
+ }
+ case 'u': {
+ switch (op[13]) {
+ case '3': return makeUnary(s, UnaryOp::TruncUFloat32ToInt32); // i32.trunc_u/f32
+ case '6': return makeUnary(s, UnaryOp::TruncUFloat64ToInt32); // i32.trunc_u/f64
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'w': {
+ switch (op[5]) {
+ case 'a': return makeAtomicWait(s, i32); // i32.wait
+ case 'r': return makeUnary(s, UnaryOp::WrapInt64); // i32.wrap/i64
+ default: goto parse_error;
+ }
+ }
+ case 'x': return makeBinary(s, BinaryOp::XorInt32); // i32.xor
+ default: goto parse_error;
+ }
+ }
+ case '6': {
+ switch (op[4]) {
+ case 'a': {
+ switch (op[5]) {
+ case 'd': return makeBinary(s, BinaryOp::AddInt64); // i64.add
+ case 'n': return makeBinary(s, BinaryOp::AndInt64); // i64.and
+ case 't': {
+ switch (op[11]) {
+ case 'l': {
+ switch (op[15]) {
+ case '\0': return makeLoad(s, i64, /*isAtomic=*/true); // i64.atomic.load
+ case '1': return makeLoad(s, i64, /*isAtomic=*/true); // i64.atomic.load16_u
+ case '3': return makeLoad(s, i64, /*isAtomic=*/true); // i64.atomic.load32_u
+ case '8': return makeLoad(s, i64, /*isAtomic=*/true); // i64.atomic.load8_u
+ default: goto parse_error;
+ }
+ }
+ case 'r': return makeAtomicRMWOrCmpxchg(s, i64); // i64.atomic.rmw.add | i64.atomic.rmw.and | i64.atomic.rmw.cmpxchg | i64.atomic.rmw.or | i64.atomic.rmw.sub | i64.atomic.rmw.xchg | i64.atomic.rmw.xor | i64.atomic.rmw16_u.add | i64.atomic.rmw16_u.and | i64.atomic.rmw16_u.cmpxchg | i64.atomic.rmw16_u.or | i64.atomic.rmw16_u.sub | i64.atomic.rmw16_u.xchg | i64.atomic.rmw16_u.xor | i64.atomic.rmw32_u.add | i64.atomic.rmw32_u.and | i64.atomic.rmw32_u.cmpxchg | i64.atomic.rmw32_u.or | i64.atomic.rmw32_u.sub | i64.atomic.rmw32_u.xchg | i64.atomic.rmw32_u.xor | i64.atomic.rmw8_u.add | i64.atomic.rmw8_u.and | i64.atomic.rmw8_u.cmpxchg | i64.atomic.rmw8_u.or | i64.atomic.rmw8_u.sub | i64.atomic.rmw8_u.xchg | i64.atomic.rmw8_u.xor
+ case 's': {
+ switch (op[16]) {
+ case '\0': return makeStore(s, i64, /*isAtomic=*/true); // i64.atomic.store
+ case '1': return makeStore(s, i64, /*isAtomic=*/true); // i64.atomic.store16
+ case '3': return makeStore(s, i64, /*isAtomic=*/true); // i64.atomic.store32
+ case '8': return makeStore(s, i64, /*isAtomic=*/true); // i64.atomic.store8
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'c': {
+ switch (op[5]) {
+ case 'l': return makeUnary(s, UnaryOp::ClzInt64); // i64.clz
+ case 'o': return makeConst(s, i64); // i64.const
+ case 't': return makeUnary(s, UnaryOp::CtzInt64); // i64.ctz
+ default: goto parse_error;
+ }
+ }
+ case 'd': {
+ switch (op[8]) {
+ case 's': return makeBinary(s, BinaryOp::DivSInt64); // i64.div_s
+ case 'u': return makeBinary(s, BinaryOp::DivUInt64); // i64.div_u
+ default: goto parse_error;
+ }
+ }
+ case 'e': {
+ switch (op[5]) {
+ case 'q': {
+ switch (op[6]) {
+ case '\0': return makeBinary(s, BinaryOp::EqInt64); // i64.eq
+ case 'z': return makeUnary(s, UnaryOp::EqZInt64); // i64.eqz
+ default: goto parse_error;
+ }
+ }
+ case 'x': {
+ switch (op[10]) {
+ case '1': return makeUnary(s, UnaryOp::ExtendS16Int64); // i64.extend16_s
+ case '3': return makeUnary(s, UnaryOp::ExtendS32Int64); // i64.extend32_s
+ case '8': return makeUnary(s, UnaryOp::ExtendS8Int64); // i64.extend8_s
+ case '_': {
+ switch (op[11]) {
+ case 's': return makeUnary(s, UnaryOp::ExtendSInt32); // i64.extend_s/i32
+ case 'u': return makeUnary(s, UnaryOp::ExtendUInt32); // i64.extend_u/i32
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'g': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[7]) {
+ case 's': return makeBinary(s, BinaryOp::GeSInt64); // i64.ge_s
+ case 'u': return makeBinary(s, BinaryOp::GeUInt64); // i64.ge_u
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[7]) {
+ case 's': return makeBinary(s, BinaryOp::GtSInt64); // i64.gt_s
+ case 'u': return makeBinary(s, BinaryOp::GtUInt64); // i64.gt_u
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'l': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[7]) {
+ case 's': return makeBinary(s, BinaryOp::LeSInt64); // i64.le_s
+ case 'u': return makeBinary(s, BinaryOp::LeUInt64); // i64.le_u
+ default: goto parse_error;
+ }
+ }
+ case 'o': {
+ switch (op[8]) {
+ case '\0': return makeLoad(s, i64, /*isAtomic=*/false); // i64.load
+ case '1': return makeLoad(s, i64, /*isAtomic=*/false); // i64.load16_s | i64.load16_u
+ case '3': return makeLoad(s, i64, /*isAtomic=*/false); // i64.load32_s | i64.load32_u
+ case '8': return makeLoad(s, i64, /*isAtomic=*/false); // i64.load8_s | i64.load8_u
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[7]) {
+ case 's': return makeBinary(s, BinaryOp::LtSInt64); // i64.lt_s
+ case 'u': return makeBinary(s, BinaryOp::LtUInt64); // i64.lt_u
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'm': return makeBinary(s, BinaryOp::MulInt64); // i64.mul
+ case 'n': return makeBinary(s, BinaryOp::NeInt64); // i64.ne
+ case 'o': return makeBinary(s, BinaryOp::OrInt64); // i64.or
+ case 'p': return makeUnary(s, UnaryOp::PopcntInt64); // i64.popcnt
+ case 'r': {
+ switch (op[5]) {
+ case 'e': {
+ switch (op[6]) {
+ case 'i': return makeUnary(s, UnaryOp::ReinterpretFloat64); // i64.reinterpret/f64
+ case 'm': {
+ switch (op[8]) {
+ case 's': return makeBinary(s, BinaryOp::RemSInt64); // i64.rem_s
+ case 'u': return makeBinary(s, BinaryOp::RemUInt64); // i64.rem_u
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'o': {
+ switch (op[7]) {
+ case 'l': return makeBinary(s, BinaryOp::RotLInt64); // i64.rotl
+ case 'r': return makeBinary(s, BinaryOp::RotRInt64); // i64.rotr
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 's': {
+ switch (op[5]) {
+ case 'h': {
+ switch (op[6]) {
+ case 'l': return makeBinary(s, BinaryOp::ShlInt64); // i64.shl
+ case 'r': {
+ switch (op[8]) {
+ case 's': return makeBinary(s, BinaryOp::ShrSInt64); // i64.shr_s
+ case 'u': return makeBinary(s, BinaryOp::ShrUInt64); // i64.shr_u
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[9]) {
+ case '\0': return makeStore(s, i64, /*isAtomic=*/false); // i64.store
+ case '1': return makeStore(s, i64, /*isAtomic=*/false); // i64.store16
+ case '3': return makeStore(s, i64, /*isAtomic=*/false); // i64.store32
+ case '8': return makeStore(s, i64, /*isAtomic=*/false); // i64.store8
+ default: goto parse_error;
+ }
+ }
+ case 'u': return makeBinary(s, BinaryOp::SubInt64); // i64.sub
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[10]) {
+ case 's': {
+ switch (op[13]) {
+ case '3': return makeUnary(s, UnaryOp::TruncSFloat32ToInt64); // i64.trunc_s/f32
+ case '6': return makeUnary(s, UnaryOp::TruncSFloat64ToInt64); // i64.trunc_s/f64
+ default: goto parse_error;
+ }
+ }
+ case 'u': {
+ switch (op[13]) {
+ case '3': return makeUnary(s, UnaryOp::TruncUFloat32ToInt64); // i64.trunc_u/f32
+ case '6': return makeUnary(s, UnaryOp::TruncUFloat64ToInt64); // i64.trunc_u/f64
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 'w': return makeAtomicWait(s, i64); // i64.wait
+ case 'x': return makeBinary(s, BinaryOp::XorInt64); // i64.xor
+ default: goto parse_error;
+ }
+ }
+ case 'f': return makeIf(s); // if
+ default: goto parse_error;
+ }
+ }
+ case 'l': return makeLoop(s); // loop
+ case 'n': return makeNop(); // nop
+ case 'r': return makeReturn(s); // return
+ case 's': {
+ switch (op[2]) {
+ case 'l': return makeSelect(s); // select
+ case 't': {
+ switch (op[4]) {
+ case 'g': return makeSetGlobal(s); // set_global
+ case 'l': return makeSetLocal(s); // set_local
+ default: goto parse_error;
+ }
+ }
+ default: goto parse_error;
+ }
+ }
+ case 't': {
+ switch (op[1]) {
+ case 'e': return makeTeeLocal(s); // tee_local
+ case 'h': return makeThenOrElse(s); // then
+ default: goto parse_error;
+ }
+ }
+ case 'u': return makeUnreachable(); // unreachable
+ case 'w': return makeAtomicWake(s); // wake
+ default: goto parse_error;
+}
+parse_error:
+ throw ParseException(std::string(op));
+#endif // INSTRUCTION_PARSER
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index c27f63f1b..517398c5c 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -167,8 +167,10 @@ public:
private:
Expression* makeExpression(Element& s);
- Expression* makeBinary(Element& s, BinaryOp op, Type type);
- Expression* makeUnary(Element& s, UnaryOp op, Type type);
+ Expression* makeUnreachable();
+ Expression* makeNop();
+ Expression* makeBinary(Element& s, BinaryOp op);
+ Expression* makeUnary(Element& s, UnaryOp op);
Expression* makeSelect(Element& s);
Expression* makeDrop(Element& s);
Expression* makeHost(Element& s, HostOp op);
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 79407a3f8..34022b72b 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -658,241 +658,19 @@ Expression* SExpressionWasmBuilder::parseExpression(Element& s) {
}
Expression* SExpressionWasmBuilder::makeExpression(Element& s) {
- IString id = s[0]->str();
- const char *str = id.str;
- const char *dot = strchr(str, '.');
- if (dot) {
- // type.operation (e.g. i32.add)
- Type type = stringToType(str, false, true);
- // Local copy to index into op without bounds checking.
- enum { maxNameSize = 15 };
- char op[maxNameSize + 1] = {'\0'};
- strncpy(op, dot + 1, maxNameSize);
-#define BINARY_INT_OR_FLOAT(op) (type == i32 ? BinaryOp::op##Int32 : (type == i64 ? BinaryOp::op##Int64 : (type == f32 ? BinaryOp::op##Float32 : BinaryOp::op##Float64)))
-#define BINARY_INT(op) (type == i32 ? BinaryOp::op##Int32 : BinaryOp::op##Int64)
-#define BINARY_FLOAT(op) (type == f32 ? BinaryOp::op##Float32 : BinaryOp::op##Float64)
- switch (op[0]) {
- case 'a': {
- if (op[1] == 'b') return makeUnary(s, type == f32 ? UnaryOp::AbsFloat32 : UnaryOp::AbsFloat64, type);
- if (op[1] == 'd') return makeBinary(s, BINARY_INT_OR_FLOAT(Add), type);
- if (op[1] == 'n') return makeBinary(s, BINARY_INT(And), type);
- if (op[1] == 't' && !strncmp(op, "atomic.", strlen("atomic."))) {
- if (op[7] == 'l') return makeLoad(s, type, /*isAtomic=*/true);
- if (op[7] == 's') return makeStore(s, type, /*isAtomic=*/true);
- if (op[7] == 'r') return makeAtomicRMWOrCmpxchg(s, type);
- }
- abort_on(op);
- }
- case 'c': {
- if (op[1] == 'e') return makeUnary(s, type == f32 ? UnaryOp::CeilFloat32 : UnaryOp::CeilFloat64, type);
- if (op[1] == 'l') return makeUnary(s, type == i32 ? UnaryOp::ClzInt32 : UnaryOp::ClzInt64, type);
- if (op[1] == 'o') {
- if (op[2] == 'p') return makeBinary(s, BINARY_FLOAT(CopySign), type);
- if (op[2] == 'n') {
- if (op[3] == 'v') {
- if (op[8] == 's') return makeUnary(s, op[11] == '3' ? (type == f32 ? UnaryOp::ConvertSInt32ToFloat32 : UnaryOp::ConvertSInt32ToFloat64) : (type == f32 ? UnaryOp::ConvertSInt64ToFloat32 : UnaryOp::ConvertSInt64ToFloat64), type);
- if (op[8] == 'u') return makeUnary(s, op[11] == '3' ? (type == f32 ? UnaryOp::ConvertUInt32ToFloat32 : UnaryOp::ConvertUInt32ToFloat64) : (type == f32 ? UnaryOp::ConvertUInt64ToFloat32 : UnaryOp::ConvertUInt64ToFloat64), type);
- }
- if (op[3] == 's') return makeConst(s, type);
- }
- }
- if (op[1] == 't') return makeUnary(s, type == i32 ? UnaryOp::CtzInt32 : UnaryOp::CtzInt64, type);
- abort_on(op);
- }
- case 'd': {
- if (op[1] == 'i') {
- if (op[3] == '_') return makeBinary(s, op[4] == 'u' ? BINARY_INT(DivU) : BINARY_INT(DivS), type);
- if (op[3] == 0) return makeBinary(s, BINARY_FLOAT(Div), type);
- }
- if (op[1] == 'e') return makeUnary(s, UnaryOp::DemoteFloat64, type);
- abort_on(op);
- }
- case 'e': {
- if (op[1] == 'q') {
- if (op[2] == 0) return makeBinary(s, BINARY_INT_OR_FLOAT(Eq), type);
- if (op[2] == 'z') return makeUnary(s, type == i32 ? UnaryOp::EqZInt32 : UnaryOp::EqZInt64, type);
- }
- if (op[1] == 'x') {
- if (op[6] == '8') return makeUnary(s, type == i32 ? UnaryOp::ExtendS8Int32 : UnaryOp::ExtendS8Int64, type);
- if (op[6] == '1') return makeUnary(s, type == i32 ? UnaryOp::ExtendS16Int32 : UnaryOp::ExtendS16Int64, type);
- if (op[6] == '3') return makeUnary(s, UnaryOp::ExtendS32Int64, type);
- return makeUnary(s, op[7] == 'u' ? UnaryOp::ExtendUInt32 : UnaryOp::ExtendSInt32, type);
- }
- abort_on(op);
- }
- case 'f': {
- if (op[1] == 'l') return makeUnary(s, type == f32 ? UnaryOp::FloorFloat32 : UnaryOp::FloorFloat64, type);
- abort_on(op);
- }
- case 'g': {
- if (op[1] == 't') {
- if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BINARY_INT(GtU) : BINARY_INT(GtS), type);
- if (op[2] == 0) return makeBinary(s, BINARY_FLOAT(Gt), type);
- }
- if (op[1] == 'e') {
- if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BINARY_INT(GeU) : BINARY_INT(GeS), type);
- if (op[2] == 0) return makeBinary(s, BINARY_FLOAT(Ge), type);
- }
- abort_on(op);
- }
- case 'l': {
- if (op[1] == 't') {
- if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BINARY_INT(LtU) : BINARY_INT(LtS), type);
- if (op[2] == 0) return makeBinary(s, BINARY_FLOAT(Lt), type);
- }
- if (op[1] == 'e') {
- if (op[2] == '_') return makeBinary(s, op[3] == 'u' ? BINARY_INT(LeU) : BINARY_INT(LeS), type);
- if (op[2] == 0) return makeBinary(s, BINARY_FLOAT(Le), type);
- }
- if (op[1] == 'o') return makeLoad(s, type, /*isAtomic=*/false);
- abort_on(op);
- }
- case 'm': {
- if (op[1] == 'i') return makeBinary(s, BINARY_FLOAT(Min), type);
- if (op[1] == 'a') return makeBinary(s, BINARY_FLOAT(Max), type);
- if (op[1] == 'u') return makeBinary(s, BINARY_INT_OR_FLOAT(Mul), type);
- abort_on(op);
- }
- case 'n': {
- if (op[1] == 'e') {
- if (op[2] == 0) return makeBinary(s, BINARY_INT_OR_FLOAT(Ne), type);
- if (op[2] == 'a') return makeUnary(s, type == f32 ? UnaryOp::NearestFloat32 : UnaryOp::NearestFloat64, type);
- if (op[2] == 'g') return makeUnary(s, type == f32 ? UnaryOp::NegFloat32 : UnaryOp::NegFloat64, type);
- }
- abort_on(op);
- }
- case 'o': {
- if (op[1] == 'r') return makeBinary(s, BINARY_INT(Or), type);
- abort_on(op);
- }
- case 'p': {
- if (op[1] == 'r') return makeUnary(s, UnaryOp::PromoteFloat32, type);
- if (op[1] == 'o') return makeUnary(s, type == i32 ? UnaryOp::PopcntInt32 : UnaryOp::PopcntInt64, type);
- abort_on(op);
- }
- case 'r': {
- if (op[1] == 'e') {
- if (op[2] == 'm') return makeBinary(s, op[4] == 'u' ? BINARY_INT(RemU) : BINARY_INT(RemS), type);
- if (op[2] == 'i') return makeUnary(s, isFloatType(type) ? (type == f32 ? UnaryOp::ReinterpretInt32 : UnaryOp::ReinterpretInt64) : (type == i32 ? UnaryOp::ReinterpretFloat32 : UnaryOp::ReinterpretFloat64), type);
- }
- if (op[1] == 'o' && op[2] == 't') {
- return makeBinary(s, op[3] == 'l' ? BINARY_INT(RotL) : BINARY_INT(RotR), type);
- }
- abort_on(op);
- }
- case 's': {
- if (op[1] == 'h') {
- if (op[2] == 'l') return makeBinary(s, BINARY_INT(Shl), type);
- return makeBinary(s, op[4] == 'u' ? BINARY_INT(ShrU) : BINARY_INT(ShrS), type);
- }
- if (op[1] == 'u') return makeBinary(s, BINARY_INT_OR_FLOAT(Sub), type);
- if (op[1] == 'q') return makeUnary(s, type == f32 ? UnaryOp::SqrtFloat32 : UnaryOp::SqrtFloat64, type);
- if (op[1] == 't') return makeStore(s, type, /*isAtomic=*/false);
- abort_on(op);
- }
- case 't': {
- if (op[1] == 'r') {
- if (op[6] == 's') return makeUnary(s, op[9] == '3' ? (type == i32 ? UnaryOp::TruncSFloat32ToInt32 : UnaryOp::TruncSFloat32ToInt64) : (type == i32 ? UnaryOp::TruncSFloat64ToInt32 : UnaryOp::TruncSFloat64ToInt64), type);
- if (op[6] == 'u') return makeUnary(s, op[9] == '3' ? (type == i32 ? UnaryOp::TruncUFloat32ToInt32 : UnaryOp::TruncUFloat32ToInt64) : (type == i32 ? UnaryOp::TruncUFloat64ToInt32 : UnaryOp::TruncUFloat64ToInt64), type);
- if (op[2] == 'u') return makeUnary(s, type == f32 ? UnaryOp::TruncFloat32 : UnaryOp::TruncFloat64, type);
- }
- abort_on(op);
- }
- case 'w': {
- if (!strncmp(op, "wait", strlen("wait"))) return makeAtomicWait(s, type);
- if (op[1] == 'r') return makeUnary(s, UnaryOp::WrapInt64, type);
- abort_on(op);
- }
- case 'x': {
- if (op[1] == 'o') return makeBinary(s, BINARY_INT(Xor), type);
- abort_on(op);
- }
- default: abort_on(op);
- }
- } else {
- // other expression
- switch (str[0]) {
- case 'b': {
- if (str[1] == 'l') return makeBlock(s);
- if (str[1] == 'r') {
- if (str[2] == '_' && str[3] == 't') return makeBreakTable(s);
- return makeBreak(s);
- }
- abort_on(str);
- }
- case 'c': {
- if (str[1] == 'a') {
- if (id == CALL) return makeCall(s);
- if (id == CALL_INDIRECT) return makeCallIndirect(s);
- } else if (str[1] == 'u') return makeHost(s, HostOp::CurrentMemory);
- abort_on(str);
- }
- case 'd': {
- if (str[1] == 'r') return makeDrop(s);
- abort_on(str);
- }
- case 'e': {
- if (str[1] == 'l') return makeThenOrElse(s);
- abort_on(str);
- }
- case 'g': {
- if (str[1] == 'e') {
- if (str[4] == 'l') return makeGetLocal(s);
- if (str[4] == 'g') return makeGetGlobal(s);
- }
- if (str[1] == 'r') return makeHost(s, HostOp::GrowMemory);
- abort_on(str);
- }
- case 'h': {
- abort_on(str);
- }
- case 'i': {
- if (str[1] == 'f') return makeIf(s);
- abort_on(str);
- }
- case 'l': {
- if (str[1] == 'o') return makeLoop(s);
- abort_on(str);
- }
- case 'n': {
- if (str[1] == 'o') return allocator.alloc<Nop>();
- abort_on(str);
- }
- case 'p': {
- abort_on(str);
- }
- case 's': {
- if (str[1] == 'e' && str[2] == 't') {
- if (str[4] == 'l') return makeSetLocal(s);
- if (str[4] == 'g') return makeSetGlobal(s);
- }
- if (str[1] == 'e' && str[2] == 'l') return makeSelect(s);
- abort_on(str);
- }
- case 'r': {
- if (str[1] == 'e') return makeReturn(s);
- abort_on(str);
- }
- case 't': {
- if (str[1] == 'h') return makeThenOrElse(s);
- if (str[1] == 'e' && str[2] == 'e') return makeTeeLocal(s);
- abort_on(str);
- }
- case 'u': {
- if (str[1] == 'n') return allocator.alloc<Unreachable>();
- abort_on(str);
- }
- case 'w': {
- if (!strncmp(str, "wake", strlen("wake"))) return makeAtomicWake(s);
- abort_on(str);
- }
- default: abort_on(str);
- }
- }
- abort_on("unrecognized input string for parsing");
+#define INSTRUCTION_PARSER
+#include "gen-s-parser.inc"
}
-Expression* SExpressionWasmBuilder::makeBinary(Element& s, BinaryOp op, Type type) {
+Expression* SExpressionWasmBuilder::makeUnreachable() {
+ return allocator.alloc<Unreachable>();
+}
+
+Expression* SExpressionWasmBuilder::makeNop() {
+ return allocator.alloc<Nop>();
+}
+
+Expression* SExpressionWasmBuilder::makeBinary(Element& s, BinaryOp op) {
auto ret = allocator.alloc<Binary>();
ret->op = op;
ret->left = parseExpression(s[1]);
@@ -902,67 +680,11 @@ Expression* SExpressionWasmBuilder::makeBinary(Element& s, BinaryOp op, Type typ
}
-Expression* SExpressionWasmBuilder::makeUnary(Element& s, UnaryOp op, Type type) {
+Expression* SExpressionWasmBuilder::makeUnary(Element& s, UnaryOp op) {
auto ret = allocator.alloc<Unary>();
ret->op = op;
ret->value = parseExpression(s[1]);
ret->finalize();
- // type is the reported type, e.g. i64.ctz reports i64 (but has a return type of i32, in this case)
- // verify the reported type is correct
- switch (op) {
- case EqZInt32:
- case NegFloat32:
- case AbsFloat32:
- case CeilFloat32:
- case FloorFloat32:
- case TruncFloat32:
- case NearestFloat32:
- case SqrtFloat32:
- case ClzInt32:
- case CtzInt32:
- case PopcntInt32:
- case EqZInt64:
- case NegFloat64:
- case AbsFloat64:
- case CeilFloat64:
- case FloorFloat64:
- case TruncFloat64:
- case NearestFloat64:
- case SqrtFloat64:
- case ClzInt64:
- case CtzInt64:
- case PopcntInt64: {
- if (ret->value->type != unreachable && type != ret->value->type) throw ParseException(std::string("bad type for ") + getExpressionName(ret) + ": " + printType(type) + " vs value type " + printType(ret->value->type), s.line, s.col);
- break;
- }
- case ExtendSInt32: case ExtendUInt32:
- case ExtendS8Int32: case ExtendS16Int32:
- case ExtendS8Int64: case ExtendS16Int64: case ExtendS32Int64:
- case WrapInt64:
- case PromoteFloat32:
- case DemoteFloat64:
- case TruncSFloat32ToInt32:
- case TruncUFloat32ToInt32:
- case TruncSFloat64ToInt32:
- case TruncUFloat64ToInt32:
- case ReinterpretFloat32:
- case TruncSFloat32ToInt64:
- case TruncUFloat32ToInt64:
- case TruncSFloat64ToInt64:
- case TruncUFloat64ToInt64:
- case ReinterpretFloat64:
- case ReinterpretInt32:
- case ConvertSInt32ToFloat32:
- case ConvertUInt32ToFloat32:
- case ConvertSInt64ToFloat32:
- case ConvertUInt64ToFloat32:
- case ReinterpretInt64:
- case ConvertSInt32ToFloat64:
- case ConvertUInt32ToFloat64:
- case ConvertSInt64ToFloat64:
- case ConvertUInt64ToFloat64: break;
- default: WASM_UNREACHABLE();
- }
return ret;
}
diff --git a/test/ctor-eval/basics-flatten.wast b/test/ctor-eval/basics-flatten.wast
index da8b76163..07078bfc3 100644
--- a/test/ctor-eval/basics-flatten.wast
+++ b/test/ctor-eval/basics-flatten.wast
@@ -17,8 +17,10 @@
)
(func $test2
(drop (i32.load (i32.const 12))) ;; a safe load
- (drop (i32.load16 (i32.const 12)))
- (drop (i32.load8 (i32.const 12)))
+ (drop (i32.load16_s (i32.const 12)))
+ (drop (i32.load8_s (i32.const 12)))
+ (drop (i32.load16_u (i32.const 12)))
+ (drop (i32.load8_u (i32.const 12)))
)
(func $test3
(i32.store (i32.const 12) (i32.const 115)) ;; a safe store, should alter memory
diff --git a/test/ctor-eval/basics.wast b/test/ctor-eval/basics.wast
index 997e2cd11..73988c753 100644
--- a/test/ctor-eval/basics.wast
+++ b/test/ctor-eval/basics.wast
@@ -14,8 +14,10 @@
)
(func $test2
(drop (i32.load (i32.const 12))) ;; a safe load
- (drop (i32.load16 (i32.const 12)))
- (drop (i32.load8 (i32.const 12)))
+ (drop (i32.load16_s (i32.const 12)))
+ (drop (i32.load8_s (i32.const 12)))
+ (drop (i32.load16_u (i32.const 12)))
+ (drop (i32.load8_u (i32.const 12)))
)
(func $test3
(i32.store (i32.const 12) (i32.const 115)) ;; a safe store, should alter memory
diff --git a/test/passes/duplicate-function-elimination_optimize-level=1.wast b/test/passes/duplicate-function-elimination_optimize-level=1.wast
index b79032155..05dbe646b 100644
--- a/test/passes/duplicate-function-elimination_optimize-level=1.wast
+++ b/test/passes/duplicate-function-elimination_optimize-level=1.wast
@@ -733,7 +733,7 @@
(memory 10)
(type $0 (func))
(func $keep2 (type $0)
- (i32.store32 offset=3
+ (i32.store offset=3
(i32.const 0)
(i32.const 100)
)
diff --git a/test/passes/duplicate-function-elimination_optimize-level=2.wast b/test/passes/duplicate-function-elimination_optimize-level=2.wast
index b79032155..05dbe646b 100644
--- a/test/passes/duplicate-function-elimination_optimize-level=2.wast
+++ b/test/passes/duplicate-function-elimination_optimize-level=2.wast
@@ -733,7 +733,7 @@
(memory 10)
(type $0 (func))
(func $keep2 (type $0)
- (i32.store32 offset=3
+ (i32.store offset=3
(i32.const 0)
(i32.const 100)
)
diff --git a/test/wasm2js/br_table_temp.wast b/test/wasm2js/br_table_temp.wast
index abd66053a..1ab685a7b 100644
--- a/test/wasm2js/br_table_temp.wast
+++ b/test/wasm2js/br_table_temp.wast
@@ -1057,7 +1057,7 @@
)
(func (export "as-unary-operand") (result i32)
- (block i32 (i32.neg (br_table 0 (i32.const 3) (i32.const 0))))
+ (block i32 (i32.ctz (br_table 0 (i32.const 3) (i32.const 0))))
)
(func (export "as-binary-left") (result i32)