diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d997e70255..a3c72ffa5a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,9 +28,7 @@ Current Trunk the PassOptions. As a result `BinaryenModulePrintStackIR` and similar APIs do not receive an `optimize` flag, as they read the PassOption `optimizeStackIR` instead. - - The new, standards-compliant text parser is now the default. `wasm-opt` has a - `--deprecated-wat-parser` flag that will switch back to using the old text - parser, but that option will go away soon. + - The new, standards-compliant text parser is now the default. - Source map comments on `else` branches must now be placed above the instruction inside the `else` branch rather than on the `else` branch itself. - Source map locations from instructions are no longer automatically propagated diff --git a/Contributing.md b/Contributing.md index 6a738f9a342..98f9c7bedce 100644 --- a/Contributing.md +++ b/Contributing.md @@ -18,8 +18,7 @@ Use this handy checklist to make sure your new instructions are fully supported: - [ ] Interpretation added to src/wasm-interpreter.h - [ ] Effects handled in src/ir/effects.h - [ ] Precomputing handled in src/passes/Precompute.cpp - - [ ] Hashing and comparing in src/ir/ExpressionAnalyzer.cpp - - [ ] Parsing added in scripts/gen-s-parser.py, src/wasm-s-parser.h and src/wasm/wasm-s-parser.cpp + - [ ] Parsing added in scripts/gen-s-parser.py, src/parser/parsers.h, src/parser/contexts.h, src/wasm-ir-builder.h, and src/wasm/wasm-ir-builder.cpp - [ ] Printing added in src/passes/Print.cpp - [ ] Decoding added in src/wasm-binary.h and src/wasm/wasm-binary.cpp - [ ] Binary writing added in src/wasm-stack.h and src/wasm/wasm-stack.cpp @@ -30,4 +29,4 @@ Use this handy checklist to make sure your new instructions are fully supported: - [ ] C API tested in test/example/c-api-kitchen-sink.c - [ ] JS API tested in test/binaryen.js/kitchen-sink.js - [ ] Tests added in test/spec - - [ ] Tests added in top-level test/ + - [ ] Tests added in test/lit diff --git a/check.py b/check.py index dbd35c5013b..946e3a0cf27 100755 --- a/check.py +++ b/check.py @@ -195,7 +195,7 @@ def run_spec_test(wast): def run_opt_test(wast): # check optimization validation - cmd = shared.WASM_OPT + [wast, '-O', '-all', '-q', '--new-wat-parser'] + cmd = shared.WASM_OPT + [wast, '-O', '-all', '-q'] support.run_command(cmd) def check_expected(actual, expected): diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 4cf2e8ee9d1..d75be7635fc 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -19,608 +19,608 @@ instructions = [ ("unreachable", "makeUnreachable()"), ("nop", "makeNop()"), - ("block", "makeBlock(s)"), - ("loop", "makeLoop(s)"), - ("if", "makeIf(s)"), - ("then", "makeThenOrElse(s)"), - ("else", "makeThenOrElse(s)"), - ("br", "makeBreak(s, false)"), - ("br_if", "makeBreak(s, true)"), - ("br_table", "makeBreakTable(s)"), - ("return", "makeReturn(s)"), - ("call", "makeCall(s, /*isReturn=*/false)"), - ("call_indirect", "makeCallIndirect(s, /*isReturn=*/false)"), - ("return_call", "makeCall(s, /*isReturn=*/true)"), - ("return_call_indirect", "makeCallIndirect(s, /*isReturn=*/true)"), - ("drop", "makeDrop(s)"), - ("select", "makeSelect(s)"), - ("local.get", "makeLocalGet(s)"), - ("local.set", "makeLocalSet(s)"), - ("local.tee", "makeLocalTee(s)"), - ("global.get", "makeGlobalGet(s)"), - ("global.set", "makeGlobalSet(s)"), - ("memory.init", "makeMemoryInit(s)"), - ("data.drop", "makeDataDrop(s)"), - ("memory.copy", "makeMemoryCopy(s)"), - ("memory.fill", "makeMemoryFill(s)"), - ("i32.load", "makeLoad(s, Type::i32, /*signed=*/false, 4, /*isAtomic=*/false)"), - ("i64.load", "makeLoad(s, Type::i64, /*signed=*/false, 8, /*isAtomic=*/false)"), - ("f32.load", "makeLoad(s, Type::f32, /*signed=*/false, 4, /*isAtomic=*/false)"), - ("f64.load", "makeLoad(s, Type::f64, /*signed=*/false, 8, /*isAtomic=*/false)"), - ("i32.load8_s", "makeLoad(s, Type::i32, /*signed=*/true, 1, /*isAtomic=*/false)"), - ("i32.load8_u", "makeLoad(s, Type::i32, /*signed=*/false, 1, /*isAtomic=*/false)"), - ("i32.load16_s", "makeLoad(s, Type::i32, /*signed=*/true, 2, /*isAtomic=*/false)"), - ("i32.load16_u", "makeLoad(s, Type::i32, /*signed=*/false, 2, /*isAtomic=*/false)"), - ("i64.load8_s", "makeLoad(s, Type::i64, /*signed=*/true, 1, /*isAtomic=*/false)"), - ("i64.load8_u", "makeLoad(s, Type::i64, /*signed=*/false, 1, /*isAtomic=*/false)"), - ("i64.load16_s", "makeLoad(s, Type::i64, /*signed=*/true, 2, /*isAtomic=*/false)"), - ("i64.load16_u", "makeLoad(s, Type::i64, /*signed=*/false, 2, /*isAtomic=*/false)"), - ("i64.load32_s", "makeLoad(s, Type::i64, /*signed=*/true, 4, /*isAtomic=*/false)"), - ("i64.load32_u", "makeLoad(s, Type::i64, /*signed=*/false, 4, /*isAtomic=*/false)"), - ("i32.store", "makeStore(s, Type::i32, 4, /*isAtomic=*/false)"), - ("i64.store", "makeStore(s, Type::i64, 8, /*isAtomic=*/false)"), - ("f32.store", "makeStore(s, Type::f32, 4, /*isAtomic=*/false)"), - ("f64.store", "makeStore(s, Type::f64, 8, /*isAtomic=*/false)"), - ("i32.store8", "makeStore(s, Type::i32, 1, /*isAtomic=*/false)"), - ("i32.store16", "makeStore(s, Type::i32, 2, /*isAtomic=*/false)"), - ("i64.store8", "makeStore(s, Type::i64, 1, /*isAtomic=*/false)"), - ("i64.store16", "makeStore(s, Type::i64, 2, /*isAtomic=*/false)"), - ("i64.store32", "makeStore(s, Type::i64, 4, /*isAtomic=*/false)"), - ("memory.size", "makeMemorySize(s)"), - ("memory.grow", "makeMemoryGrow(s)"), - ("i32.const", "makeConst(s, Type::i32)"), - ("i64.const", "makeConst(s, Type::i64)"), - ("f32.const", "makeConst(s, Type::f32)"), - ("f64.const", "makeConst(s, Type::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_f32_s", "makeUnary(s, UnaryOp::TruncSFloat32ToInt32)"), - ("i32.trunc_f32_u", "makeUnary(s, UnaryOp::TruncUFloat32ToInt32)"), - ("i32.trunc_f64_s", "makeUnary(s, UnaryOp::TruncSFloat64ToInt32)"), - ("i32.trunc_f64_u", "makeUnary(s, UnaryOp::TruncUFloat64ToInt32)"), - ("i64.extend_i32_s", "makeUnary(s, UnaryOp::ExtendSInt32)"), - ("i64.extend_i32_u", "makeUnary(s, UnaryOp::ExtendUInt32)"), - ("i64.trunc_f32_s", "makeUnary(s, UnaryOp::TruncSFloat32ToInt64)"), - ("i64.trunc_f32_u", "makeUnary(s, UnaryOp::TruncUFloat32ToInt64)"), - ("i64.trunc_f64_s", "makeUnary(s, UnaryOp::TruncSFloat64ToInt64)"), - ("i64.trunc_f64_u", "makeUnary(s, UnaryOp::TruncUFloat64ToInt64)"), - ("f32.convert_i32_s", "makeUnary(s, UnaryOp::ConvertSInt32ToFloat32)"), - ("f32.convert_i32_u", "makeUnary(s, UnaryOp::ConvertUInt32ToFloat32)"), - ("f32.convert_i64_s", "makeUnary(s, UnaryOp::ConvertSInt64ToFloat32)"), - ("f32.convert_i64_u", "makeUnary(s, UnaryOp::ConvertUInt64ToFloat32)"), - ("f32.demote_f64", "makeUnary(s, UnaryOp::DemoteFloat64)"), - ("f64.convert_i32_s", "makeUnary(s, UnaryOp::ConvertSInt32ToFloat64)"), - ("f64.convert_i32_u", "makeUnary(s, UnaryOp::ConvertUInt32ToFloat64)"), - ("f64.convert_i64_s", "makeUnary(s, UnaryOp::ConvertSInt64ToFloat64)"), - ("f64.convert_i64_u", "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)"), + ("block", "makeBlock()"), + ("loop", "makeLoop()"), + ("if", "makeIf()"), + ("then", "makeThenOrElse()"), + ("else", "makeThenOrElse()"), + ("br", "makeBreak(false)"), + ("br_if", "makeBreak(true)"), + ("br_table", "makeBreakTable()"), + ("return", "makeReturn()"), + ("call", "makeCall(/*isReturn=*/false)"), + ("call_indirect", "makeCallIndirect(/*isReturn=*/false)"), + ("return_call", "makeCall(/*isReturn=*/true)"), + ("return_call_indirect", "makeCallIndirect(/*isReturn=*/true)"), + ("drop", "makeDrop()"), + ("select", "makeSelect()"), + ("local.get", "makeLocalGet()"), + ("local.set", "makeLocalSet()"), + ("local.tee", "makeLocalTee()"), + ("global.get", "makeGlobalGet()"), + ("global.set", "makeGlobalSet()"), + ("memory.init", "makeMemoryInit()"), + ("data.drop", "makeDataDrop()"), + ("memory.copy", "makeMemoryCopy()"), + ("memory.fill", "makeMemoryFill()"), + ("i32.load", "makeLoad(Type::i32, /*signed=*/false, 4, /*isAtomic=*/false)"), + ("i64.load", "makeLoad(Type::i64, /*signed=*/false, 8, /*isAtomic=*/false)"), + ("f32.load", "makeLoad(Type::f32, /*signed=*/false, 4, /*isAtomic=*/false)"), + ("f64.load", "makeLoad(Type::f64, /*signed=*/false, 8, /*isAtomic=*/false)"), + ("i32.load8_s", "makeLoad(Type::i32, /*signed=*/true, 1, /*isAtomic=*/false)"), + ("i32.load8_u", "makeLoad(Type::i32, /*signed=*/false, 1, /*isAtomic=*/false)"), + ("i32.load16_s", "makeLoad(Type::i32, /*signed=*/true, 2, /*isAtomic=*/false)"), + ("i32.load16_u", "makeLoad(Type::i32, /*signed=*/false, 2, /*isAtomic=*/false)"), + ("i64.load8_s", "makeLoad(Type::i64, /*signed=*/true, 1, /*isAtomic=*/false)"), + ("i64.load8_u", "makeLoad(Type::i64, /*signed=*/false, 1, /*isAtomic=*/false)"), + ("i64.load16_s", "makeLoad(Type::i64, /*signed=*/true, 2, /*isAtomic=*/false)"), + ("i64.load16_u", "makeLoad(Type::i64, /*signed=*/false, 2, /*isAtomic=*/false)"), + ("i64.load32_s", "makeLoad(Type::i64, /*signed=*/true, 4, /*isAtomic=*/false)"), + ("i64.load32_u", "makeLoad(Type::i64, /*signed=*/false, 4, /*isAtomic=*/false)"), + ("i32.store", "makeStore(Type::i32, 4, /*isAtomic=*/false)"), + ("i64.store", "makeStore(Type::i64, 8, /*isAtomic=*/false)"), + ("f32.store", "makeStore(Type::f32, 4, /*isAtomic=*/false)"), + ("f64.store", "makeStore(Type::f64, 8, /*isAtomic=*/false)"), + ("i32.store8", "makeStore(Type::i32, 1, /*isAtomic=*/false)"), + ("i32.store16", "makeStore(Type::i32, 2, /*isAtomic=*/false)"), + ("i64.store8", "makeStore(Type::i64, 1, /*isAtomic=*/false)"), + ("i64.store16", "makeStore(Type::i64, 2, /*isAtomic=*/false)"), + ("i64.store32", "makeStore(Type::i64, 4, /*isAtomic=*/false)"), + ("memory.size", "makeMemorySize()"), + ("memory.grow", "makeMemoryGrow()"), + ("i32.const", "makeConst(Type::i32)"), + ("i64.const", "makeConst(Type::i64)"), + ("f32.const", "makeConst(Type::f32)"), + ("f64.const", "makeConst(Type::f64)"), + ("i32.eqz", "makeUnary(UnaryOp::EqZInt32)"), + ("i32.eq", "makeBinary(BinaryOp::EqInt32)"), + ("i32.ne", "makeBinary(BinaryOp::NeInt32)"), + ("i32.lt_s", "makeBinary(BinaryOp::LtSInt32)"), + ("i32.lt_u", "makeBinary(BinaryOp::LtUInt32)"), + ("i32.gt_s", "makeBinary(BinaryOp::GtSInt32)"), + ("i32.gt_u", "makeBinary(BinaryOp::GtUInt32)"), + ("i32.le_s", "makeBinary(BinaryOp::LeSInt32)"), + ("i32.le_u", "makeBinary(BinaryOp::LeUInt32)"), + ("i32.ge_s", "makeBinary(BinaryOp::GeSInt32)"), + ("i32.ge_u", "makeBinary(BinaryOp::GeUInt32)"), + ("i64.eqz", "makeUnary(UnaryOp::EqZInt64)"), + ("i64.eq", "makeBinary(BinaryOp::EqInt64)"), + ("i64.ne", "makeBinary(BinaryOp::NeInt64)"), + ("i64.lt_s", "makeBinary(BinaryOp::LtSInt64)"), + ("i64.lt_u", "makeBinary(BinaryOp::LtUInt64)"), + ("i64.gt_s", "makeBinary(BinaryOp::GtSInt64)"), + ("i64.gt_u", "makeBinary(BinaryOp::GtUInt64)"), + ("i64.le_s", "makeBinary(BinaryOp::LeSInt64)"), + ("i64.le_u", "makeBinary(BinaryOp::LeUInt64)"), + ("i64.ge_s", "makeBinary(BinaryOp::GeSInt64)"), + ("i64.ge_u", "makeBinary(BinaryOp::GeUInt64)"), + ("f32.eq", "makeBinary(BinaryOp::EqFloat32)"), + ("f32.ne", "makeBinary(BinaryOp::NeFloat32)"), + ("f32.lt", "makeBinary(BinaryOp::LtFloat32)"), + ("f32.gt", "makeBinary(BinaryOp::GtFloat32)"), + ("f32.le", "makeBinary(BinaryOp::LeFloat32)"), + ("f32.ge", "makeBinary(BinaryOp::GeFloat32)"), + ("f64.eq", "makeBinary(BinaryOp::EqFloat64)"), + ("f64.ne", "makeBinary(BinaryOp::NeFloat64)"), + ("f64.lt", "makeBinary(BinaryOp::LtFloat64)"), + ("f64.gt", "makeBinary(BinaryOp::GtFloat64)"), + ("f64.le", "makeBinary(BinaryOp::LeFloat64)"), + ("f64.ge", "makeBinary(BinaryOp::GeFloat64)"), + ("i32.clz", "makeUnary(UnaryOp::ClzInt32)"), + ("i32.ctz", "makeUnary(UnaryOp::CtzInt32)"), + ("i32.popcnt", "makeUnary(UnaryOp::PopcntInt32)"), + ("i32.add", "makeBinary(BinaryOp::AddInt32)"), + ("i32.sub", "makeBinary(BinaryOp::SubInt32)"), + ("i32.mul", "makeBinary(BinaryOp::MulInt32)"), + ("i32.div_s", "makeBinary(BinaryOp::DivSInt32)"), + ("i32.div_u", "makeBinary(BinaryOp::DivUInt32)"), + ("i32.rem_s", "makeBinary(BinaryOp::RemSInt32)"), + ("i32.rem_u", "makeBinary(BinaryOp::RemUInt32)"), + ("i32.and", "makeBinary(BinaryOp::AndInt32)"), + ("i32.or", "makeBinary(BinaryOp::OrInt32)"), + ("i32.xor", "makeBinary(BinaryOp::XorInt32)"), + ("i32.shl", "makeBinary(BinaryOp::ShlInt32)"), + ("i32.shr_s", "makeBinary(BinaryOp::ShrSInt32)"), + ("i32.shr_u", "makeBinary(BinaryOp::ShrUInt32)"), + ("i32.rotl", "makeBinary(BinaryOp::RotLInt32)"), + ("i32.rotr", "makeBinary(BinaryOp::RotRInt32)"), + ("i64.clz", "makeUnary(UnaryOp::ClzInt64)"), + ("i64.ctz", "makeUnary(UnaryOp::CtzInt64)"), + ("i64.popcnt", "makeUnary(UnaryOp::PopcntInt64)"), + ("i64.add", "makeBinary(BinaryOp::AddInt64)"), + ("i64.sub", "makeBinary(BinaryOp::SubInt64)"), + ("i64.mul", "makeBinary(BinaryOp::MulInt64)"), + ("i64.div_s", "makeBinary(BinaryOp::DivSInt64)"), + ("i64.div_u", "makeBinary(BinaryOp::DivUInt64)"), + ("i64.rem_s", "makeBinary(BinaryOp::RemSInt64)"), + ("i64.rem_u", "makeBinary(BinaryOp::RemUInt64)"), + ("i64.and", "makeBinary(BinaryOp::AndInt64)"), + ("i64.or", "makeBinary(BinaryOp::OrInt64)"), + ("i64.xor", "makeBinary(BinaryOp::XorInt64)"), + ("i64.shl", "makeBinary(BinaryOp::ShlInt64)"), + ("i64.shr_s", "makeBinary(BinaryOp::ShrSInt64)"), + ("i64.shr_u", "makeBinary(BinaryOp::ShrUInt64)"), + ("i64.rotl", "makeBinary(BinaryOp::RotLInt64)"), + ("i64.rotr", "makeBinary(BinaryOp::RotRInt64)"), + ("f32.abs", "makeUnary(UnaryOp::AbsFloat32)"), + ("f32.neg", "makeUnary(UnaryOp::NegFloat32)"), + ("f32.ceil", "makeUnary(UnaryOp::CeilFloat32)"), + ("f32.floor", "makeUnary(UnaryOp::FloorFloat32)"), + ("f32.trunc", "makeUnary(UnaryOp::TruncFloat32)"), + ("f32.nearest", "makeUnary(UnaryOp::NearestFloat32)"), + ("f32.sqrt", "makeUnary(UnaryOp::SqrtFloat32)"), + ("f32.add", "makeBinary(BinaryOp::AddFloat32)"), + ("f32.sub", "makeBinary(BinaryOp::SubFloat32)"), + ("f32.mul", "makeBinary(BinaryOp::MulFloat32)"), + ("f32.div", "makeBinary(BinaryOp::DivFloat32)"), + ("f32.min", "makeBinary(BinaryOp::MinFloat32)"), + ("f32.max", "makeBinary(BinaryOp::MaxFloat32)"), + ("f32.copysign", "makeBinary(BinaryOp::CopySignFloat32)"), + ("f64.abs", "makeUnary(UnaryOp::AbsFloat64)"), + ("f64.neg", "makeUnary(UnaryOp::NegFloat64)"), + ("f64.ceil", "makeUnary(UnaryOp::CeilFloat64)"), + ("f64.floor", "makeUnary(UnaryOp::FloorFloat64)"), + ("f64.trunc", "makeUnary(UnaryOp::TruncFloat64)"), + ("f64.nearest", "makeUnary(UnaryOp::NearestFloat64)"), + ("f64.sqrt", "makeUnary(UnaryOp::SqrtFloat64)"), + ("f64.add", "makeBinary(BinaryOp::AddFloat64)"), + ("f64.sub", "makeBinary(BinaryOp::SubFloat64)"), + ("f64.mul", "makeBinary(BinaryOp::MulFloat64)"), + ("f64.div", "makeBinary(BinaryOp::DivFloat64)"), + ("f64.min", "makeBinary(BinaryOp::MinFloat64)"), + ("f64.max", "makeBinary(BinaryOp::MaxFloat64)"), + ("f64.copysign", "makeBinary(BinaryOp::CopySignFloat64)"), + ("i32.wrap_i64", "makeUnary(UnaryOp::WrapInt64)"), + ("i32.trunc_f32_s", "makeUnary(UnaryOp::TruncSFloat32ToInt32)"), + ("i32.trunc_f32_u", "makeUnary(UnaryOp::TruncUFloat32ToInt32)"), + ("i32.trunc_f64_s", "makeUnary(UnaryOp::TruncSFloat64ToInt32)"), + ("i32.trunc_f64_u", "makeUnary(UnaryOp::TruncUFloat64ToInt32)"), + ("i64.extend_i32_s", "makeUnary(UnaryOp::ExtendSInt32)"), + ("i64.extend_i32_u", "makeUnary(UnaryOp::ExtendUInt32)"), + ("i64.trunc_f32_s", "makeUnary(UnaryOp::TruncSFloat32ToInt64)"), + ("i64.trunc_f32_u", "makeUnary(UnaryOp::TruncUFloat32ToInt64)"), + ("i64.trunc_f64_s", "makeUnary(UnaryOp::TruncSFloat64ToInt64)"), + ("i64.trunc_f64_u", "makeUnary(UnaryOp::TruncUFloat64ToInt64)"), + ("f32.convert_i32_s", "makeUnary(UnaryOp::ConvertSInt32ToFloat32)"), + ("f32.convert_i32_u", "makeUnary(UnaryOp::ConvertUInt32ToFloat32)"), + ("f32.convert_i64_s", "makeUnary(UnaryOp::ConvertSInt64ToFloat32)"), + ("f32.convert_i64_u", "makeUnary(UnaryOp::ConvertUInt64ToFloat32)"), + ("f32.demote_f64", "makeUnary(UnaryOp::DemoteFloat64)"), + ("f64.convert_i32_s", "makeUnary(UnaryOp::ConvertSInt32ToFloat64)"), + ("f64.convert_i32_u", "makeUnary(UnaryOp::ConvertUInt32ToFloat64)"), + ("f64.convert_i64_s", "makeUnary(UnaryOp::ConvertSInt64ToFloat64)"), + ("f64.convert_i64_u", "makeUnary(UnaryOp::ConvertUInt64ToFloat64)"), + ("f64.promote_f32", "makeUnary(UnaryOp::PromoteFloat32)"), + ("i32.reinterpret_f32", "makeUnary(UnaryOp::ReinterpretFloat32)"), + ("i64.reinterpret_f64", "makeUnary(UnaryOp::ReinterpretFloat64)"), + ("f32.reinterpret_i32", "makeUnary(UnaryOp::ReinterpretInt32)"), + ("f64.reinterpret_i64", "makeUnary(UnaryOp::ReinterpretInt64)"), + ("i32.extend8_s", "makeUnary(UnaryOp::ExtendS8Int32)"), + ("i32.extend16_s", "makeUnary(UnaryOp::ExtendS16Int32)"), + ("i64.extend8_s", "makeUnary(UnaryOp::ExtendS8Int64)"), + ("i64.extend16_s", "makeUnary(UnaryOp::ExtendS16Int64)"), + ("i64.extend32_s", "makeUnary(UnaryOp::ExtendS32Int64)"), # atomic instructions - ("memory.atomic.notify", "makeAtomicNotify(s)"), - ("memory.atomic.wait32", "makeAtomicWait(s, Type::i32)"), - ("memory.atomic.wait64", "makeAtomicWait(s, Type::i64)"), - ("atomic.fence", "makeAtomicFence(s)"), - ("i32.atomic.load8_u", "makeLoad(s, Type::i32, /*signed=*/false, 1, /*isAtomic=*/true)"), - ("i32.atomic.load16_u", "makeLoad(s, Type::i32, /*signed=*/false, 2, /*isAtomic=*/true)"), - ("i32.atomic.load", "makeLoad(s, Type::i32, /*signed=*/false, 4, /*isAtomic=*/true)"), - ("i64.atomic.load8_u", "makeLoad(s, Type::i64, /*signed=*/false, 1, /*isAtomic=*/true)"), - ("i64.atomic.load16_u", "makeLoad(s, Type::i64, /*signed=*/false, 2, /*isAtomic=*/true)"), - ("i64.atomic.load32_u", "makeLoad(s, Type::i64, /*signed=*/false, 4, /*isAtomic=*/true)"), - ("i64.atomic.load", "makeLoad(s, Type::i64, /*signed=*/false, 8, /*isAtomic=*/true)"), - ("i32.atomic.store8", "makeStore(s, Type::i32, 1, /*isAtomic=*/true)"), - ("i32.atomic.store16", "makeStore(s, Type::i32, 2, /*isAtomic=*/true)"), - ("i32.atomic.store", "makeStore(s, Type::i32, 4, /*isAtomic=*/true)"), - ("i64.atomic.store8", "makeStore(s, Type::i64, 1, /*isAtomic=*/true)"), - ("i64.atomic.store16", "makeStore(s, Type::i64, 2, /*isAtomic=*/true)"), - ("i64.atomic.store32", "makeStore(s, Type::i64, 4, /*isAtomic=*/true)"), - ("i64.atomic.store", "makeStore(s, Type::i64, 8, /*isAtomic=*/true)"), - ("i32.atomic.rmw8.add_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i32, 1)"), - ("i32.atomic.rmw16.add_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i32, 2)"), - ("i32.atomic.rmw.add", "makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i32, 4)"), - ("i64.atomic.rmw8.add_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i64, 1)"), - ("i64.atomic.rmw16.add_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i64, 2)"), - ("i64.atomic.rmw32.add_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i64, 4)"), - ("i64.atomic.rmw.add", "makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i64, 8)"), - ("i32.atomic.rmw8.sub_u", "makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i32, 1)"), - ("i32.atomic.rmw16.sub_u", "makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i32, 2)"), - ("i32.atomic.rmw.sub", "makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i32, 4)"), - ("i64.atomic.rmw8.sub_u", "makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i64, 1)"), - ("i64.atomic.rmw16.sub_u", "makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i64, 2)"), - ("i64.atomic.rmw32.sub_u", "makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i64, 4)"), - ("i64.atomic.rmw.sub", "makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i64, 8)"), - ("i32.atomic.rmw8.and_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i32, 1)"), - ("i32.atomic.rmw16.and_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i32, 2)"), - ("i32.atomic.rmw.and", "makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i32, 4)"), - ("i64.atomic.rmw8.and_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i64, 1)"), - ("i64.atomic.rmw16.and_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i64, 2)"), - ("i64.atomic.rmw32.and_u", "makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i64, 4)"), - ("i64.atomic.rmw.and", "makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i64, 8)"), - ("i32.atomic.rmw8.or_u", "makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i32, 1)"), - ("i32.atomic.rmw16.or_u", "makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i32, 2)"), - ("i32.atomic.rmw.or", "makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i32, 4)"), - ("i64.atomic.rmw8.or_u", "makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i64, 1)"), - ("i64.atomic.rmw16.or_u", "makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i64, 2)"), - ("i64.atomic.rmw32.or_u", "makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i64, 4)"), - ("i64.atomic.rmw.or", "makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i64, 8)"), - ("i32.atomic.rmw8.xor_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i32, 1)"), - ("i32.atomic.rmw16.xor_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i32, 2)"), - ("i32.atomic.rmw.xor", "makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i32, 4)"), - ("i64.atomic.rmw8.xor_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i64, 1)"), - ("i64.atomic.rmw16.xor_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i64, 2)"), - ("i64.atomic.rmw32.xor_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i64, 4)"), - ("i64.atomic.rmw.xor", "makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i64, 8)"), - ("i32.atomic.rmw8.xchg_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i32, 1)"), - ("i32.atomic.rmw16.xchg_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i32, 2)"), - ("i32.atomic.rmw.xchg", "makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i32, 4)"), - ("i64.atomic.rmw8.xchg_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i64, 1)"), - ("i64.atomic.rmw16.xchg_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i64, 2)"), - ("i64.atomic.rmw32.xchg_u", "makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i64, 4)"), - ("i64.atomic.rmw.xchg", "makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i64, 8)"), - ("i32.atomic.rmw8.cmpxchg_u", "makeAtomicCmpxchg(s, Type::i32, 1)"), - ("i32.atomic.rmw16.cmpxchg_u", "makeAtomicCmpxchg(s, Type::i32, 2)"), - ("i32.atomic.rmw.cmpxchg", "makeAtomicCmpxchg(s, Type::i32, 4)"), - ("i64.atomic.rmw8.cmpxchg_u", "makeAtomicCmpxchg(s, Type::i64, 1)"), - ("i64.atomic.rmw16.cmpxchg_u", "makeAtomicCmpxchg(s, Type::i64, 2)"), - ("i64.atomic.rmw32.cmpxchg_u", "makeAtomicCmpxchg(s, Type::i64, 4)"), - ("i64.atomic.rmw.cmpxchg", "makeAtomicCmpxchg(s, Type::i64, 8)"), + ("memory.atomic.notify", "makeAtomicNotify()"), + ("memory.atomic.wait32", "makeAtomicWait(Type::i32)"), + ("memory.atomic.wait64", "makeAtomicWait(Type::i64)"), + ("atomic.fence", "makeAtomicFence()"), + ("i32.atomic.load8_u", "makeLoad(Type::i32, /*signed=*/false, 1, /*isAtomic=*/true)"), + ("i32.atomic.load16_u", "makeLoad(Type::i32, /*signed=*/false, 2, /*isAtomic=*/true)"), + ("i32.atomic.load", "makeLoad(Type::i32, /*signed=*/false, 4, /*isAtomic=*/true)"), + ("i64.atomic.load8_u", "makeLoad(Type::i64, /*signed=*/false, 1, /*isAtomic=*/true)"), + ("i64.atomic.load16_u", "makeLoad(Type::i64, /*signed=*/false, 2, /*isAtomic=*/true)"), + ("i64.atomic.load32_u", "makeLoad(Type::i64, /*signed=*/false, 4, /*isAtomic=*/true)"), + ("i64.atomic.load", "makeLoad(Type::i64, /*signed=*/false, 8, /*isAtomic=*/true)"), + ("i32.atomic.store8", "makeStore(Type::i32, 1, /*isAtomic=*/true)"), + ("i32.atomic.store16", "makeStore(Type::i32, 2, /*isAtomic=*/true)"), + ("i32.atomic.store", "makeStore(Type::i32, 4, /*isAtomic=*/true)"), + ("i64.atomic.store8", "makeStore(Type::i64, 1, /*isAtomic=*/true)"), + ("i64.atomic.store16", "makeStore(Type::i64, 2, /*isAtomic=*/true)"), + ("i64.atomic.store32", "makeStore(Type::i64, 4, /*isAtomic=*/true)"), + ("i64.atomic.store", "makeStore(Type::i64, 8, /*isAtomic=*/true)"), + ("i32.atomic.rmw8.add_u", "makeAtomicRMW(AtomicRMWOp::RMWAdd, Type::i32, 1)"), + ("i32.atomic.rmw16.add_u", "makeAtomicRMW(AtomicRMWOp::RMWAdd, Type::i32, 2)"), + ("i32.atomic.rmw.add", "makeAtomicRMW(AtomicRMWOp::RMWAdd, Type::i32, 4)"), + ("i64.atomic.rmw8.add_u", "makeAtomicRMW(AtomicRMWOp::RMWAdd, Type::i64, 1)"), + ("i64.atomic.rmw16.add_u", "makeAtomicRMW(AtomicRMWOp::RMWAdd, Type::i64, 2)"), + ("i64.atomic.rmw32.add_u", "makeAtomicRMW(AtomicRMWOp::RMWAdd, Type::i64, 4)"), + ("i64.atomic.rmw.add", "makeAtomicRMW(AtomicRMWOp::RMWAdd, Type::i64, 8)"), + ("i32.atomic.rmw8.sub_u", "makeAtomicRMW(AtomicRMWOp::RMWSub, Type::i32, 1)"), + ("i32.atomic.rmw16.sub_u", "makeAtomicRMW(AtomicRMWOp::RMWSub, Type::i32, 2)"), + ("i32.atomic.rmw.sub", "makeAtomicRMW(AtomicRMWOp::RMWSub, Type::i32, 4)"), + ("i64.atomic.rmw8.sub_u", "makeAtomicRMW(AtomicRMWOp::RMWSub, Type::i64, 1)"), + ("i64.atomic.rmw16.sub_u", "makeAtomicRMW(AtomicRMWOp::RMWSub, Type::i64, 2)"), + ("i64.atomic.rmw32.sub_u", "makeAtomicRMW(AtomicRMWOp::RMWSub, Type::i64, 4)"), + ("i64.atomic.rmw.sub", "makeAtomicRMW(AtomicRMWOp::RMWSub, Type::i64, 8)"), + ("i32.atomic.rmw8.and_u", "makeAtomicRMW(AtomicRMWOp::RMWAnd, Type::i32, 1)"), + ("i32.atomic.rmw16.and_u", "makeAtomicRMW(AtomicRMWOp::RMWAnd, Type::i32, 2)"), + ("i32.atomic.rmw.and", "makeAtomicRMW(AtomicRMWOp::RMWAnd, Type::i32, 4)"), + ("i64.atomic.rmw8.and_u", "makeAtomicRMW(AtomicRMWOp::RMWAnd, Type::i64, 1)"), + ("i64.atomic.rmw16.and_u", "makeAtomicRMW(AtomicRMWOp::RMWAnd, Type::i64, 2)"), + ("i64.atomic.rmw32.and_u", "makeAtomicRMW(AtomicRMWOp::RMWAnd, Type::i64, 4)"), + ("i64.atomic.rmw.and", "makeAtomicRMW(AtomicRMWOp::RMWAnd, Type::i64, 8)"), + ("i32.atomic.rmw8.or_u", "makeAtomicRMW(AtomicRMWOp::RMWOr, Type::i32, 1)"), + ("i32.atomic.rmw16.or_u", "makeAtomicRMW(AtomicRMWOp::RMWOr, Type::i32, 2)"), + ("i32.atomic.rmw.or", "makeAtomicRMW(AtomicRMWOp::RMWOr, Type::i32, 4)"), + ("i64.atomic.rmw8.or_u", "makeAtomicRMW(AtomicRMWOp::RMWOr, Type::i64, 1)"), + ("i64.atomic.rmw16.or_u", "makeAtomicRMW(AtomicRMWOp::RMWOr, Type::i64, 2)"), + ("i64.atomic.rmw32.or_u", "makeAtomicRMW(AtomicRMWOp::RMWOr, Type::i64, 4)"), + ("i64.atomic.rmw.or", "makeAtomicRMW(AtomicRMWOp::RMWOr, Type::i64, 8)"), + ("i32.atomic.rmw8.xor_u", "makeAtomicRMW(AtomicRMWOp::RMWXor, Type::i32, 1)"), + ("i32.atomic.rmw16.xor_u", "makeAtomicRMW(AtomicRMWOp::RMWXor, Type::i32, 2)"), + ("i32.atomic.rmw.xor", "makeAtomicRMW(AtomicRMWOp::RMWXor, Type::i32, 4)"), + ("i64.atomic.rmw8.xor_u", "makeAtomicRMW(AtomicRMWOp::RMWXor, Type::i64, 1)"), + ("i64.atomic.rmw16.xor_u", "makeAtomicRMW(AtomicRMWOp::RMWXor, Type::i64, 2)"), + ("i64.atomic.rmw32.xor_u", "makeAtomicRMW(AtomicRMWOp::RMWXor, Type::i64, 4)"), + ("i64.atomic.rmw.xor", "makeAtomicRMW(AtomicRMWOp::RMWXor, Type::i64, 8)"), + ("i32.atomic.rmw8.xchg_u", "makeAtomicRMW(AtomicRMWOp::RMWXchg, Type::i32, 1)"), + ("i32.atomic.rmw16.xchg_u", "makeAtomicRMW(AtomicRMWOp::RMWXchg, Type::i32, 2)"), + ("i32.atomic.rmw.xchg", "makeAtomicRMW(AtomicRMWOp::RMWXchg, Type::i32, 4)"), + ("i64.atomic.rmw8.xchg_u", "makeAtomicRMW(AtomicRMWOp::RMWXchg, Type::i64, 1)"), + ("i64.atomic.rmw16.xchg_u", "makeAtomicRMW(AtomicRMWOp::RMWXchg, Type::i64, 2)"), + ("i64.atomic.rmw32.xchg_u", "makeAtomicRMW(AtomicRMWOp::RMWXchg, Type::i64, 4)"), + ("i64.atomic.rmw.xchg", "makeAtomicRMW(AtomicRMWOp::RMWXchg, Type::i64, 8)"), + ("i32.atomic.rmw8.cmpxchg_u", "makeAtomicCmpxchg(Type::i32, 1)"), + ("i32.atomic.rmw16.cmpxchg_u", "makeAtomicCmpxchg(Type::i32, 2)"), + ("i32.atomic.rmw.cmpxchg", "makeAtomicCmpxchg(Type::i32, 4)"), + ("i64.atomic.rmw8.cmpxchg_u", "makeAtomicCmpxchg(Type::i64, 1)"), + ("i64.atomic.rmw16.cmpxchg_u", "makeAtomicCmpxchg(Type::i64, 2)"), + ("i64.atomic.rmw32.cmpxchg_u", "makeAtomicCmpxchg(Type::i64, 4)"), + ("i64.atomic.rmw.cmpxchg", "makeAtomicCmpxchg(Type::i64, 8)"), # nontrapping float-to-int instructions - ("i32.trunc_sat_f32_s", "makeUnary(s, UnaryOp::TruncSatSFloat32ToInt32)"), - ("i32.trunc_sat_f32_u", "makeUnary(s, UnaryOp::TruncSatUFloat32ToInt32)"), - ("i32.trunc_sat_f64_s", "makeUnary(s, UnaryOp::TruncSatSFloat64ToInt32)"), - ("i32.trunc_sat_f64_u", "makeUnary(s, UnaryOp::TruncSatUFloat64ToInt32)"), - ("i64.trunc_sat_f32_s", "makeUnary(s, UnaryOp::TruncSatSFloat32ToInt64)"), - ("i64.trunc_sat_f32_u", "makeUnary(s, UnaryOp::TruncSatUFloat32ToInt64)"), - ("i64.trunc_sat_f64_s", "makeUnary(s, UnaryOp::TruncSatSFloat64ToInt64)"), - ("i64.trunc_sat_f64_u", "makeUnary(s, UnaryOp::TruncSatUFloat64ToInt64)"), + ("i32.trunc_sat_f32_s", "makeUnary(UnaryOp::TruncSatSFloat32ToInt32)"), + ("i32.trunc_sat_f32_u", "makeUnary(UnaryOp::TruncSatUFloat32ToInt32)"), + ("i32.trunc_sat_f64_s", "makeUnary(UnaryOp::TruncSatSFloat64ToInt32)"), + ("i32.trunc_sat_f64_u", "makeUnary(UnaryOp::TruncSatUFloat64ToInt32)"), + ("i64.trunc_sat_f32_s", "makeUnary(UnaryOp::TruncSatSFloat32ToInt64)"), + ("i64.trunc_sat_f32_u", "makeUnary(UnaryOp::TruncSatUFloat32ToInt64)"), + ("i64.trunc_sat_f64_s", "makeUnary(UnaryOp::TruncSatSFloat64ToInt64)"), + ("i64.trunc_sat_f64_u", "makeUnary(UnaryOp::TruncSatUFloat64ToInt64)"), # SIMD ops - ("v128.load", "makeLoad(s, Type::v128, /*signed=*/false, 16, /*isAtomic=*/false)"), - ("v128.store", "makeStore(s, Type::v128, 16, /*isAtomic=*/false)"), - ("v128.const", "makeConst(s, Type::v128)"), - ("i8x16.shuffle", "makeSIMDShuffle(s)"), - ("i8x16.splat", "makeUnary(s, UnaryOp::SplatVecI8x16)"), - ("i8x16.extract_lane_s", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI8x16, 16)"), - ("i8x16.extract_lane_u", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI8x16, 16)"), - ("i8x16.replace_lane", "makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI8x16, 16)"), - ("i16x8.splat", "makeUnary(s, UnaryOp::SplatVecI16x8)"), - ("i16x8.extract_lane_s", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI16x8, 8)"), - ("i16x8.extract_lane_u", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI16x8, 8)"), - ("i16x8.replace_lane", "makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI16x8, 8)"), - ("i32x4.splat", "makeUnary(s, UnaryOp::SplatVecI32x4)"), - ("i32x4.extract_lane", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI32x4, 4)"), - ("i32x4.replace_lane", "makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI32x4, 4)"), - ("i64x2.splat", "makeUnary(s, UnaryOp::SplatVecI64x2)"), - ("i64x2.extract_lane", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI64x2, 2)"), - ("i64x2.replace_lane", "makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI64x2, 2)"), - ("f32x4.splat", "makeUnary(s, UnaryOp::SplatVecF32x4)"), - ("f32x4.extract_lane", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecF32x4, 4)"), - ("f32x4.replace_lane", "makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF32x4, 4)"), - ("f64x2.splat", "makeUnary(s, UnaryOp::SplatVecF64x2)"), - ("f64x2.extract_lane", "makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecF64x2, 2)"), - ("f64x2.replace_lane", "makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF64x2, 2)"), - ("i8x16.eq", "makeBinary(s, BinaryOp::EqVecI8x16)"), - ("i8x16.ne", "makeBinary(s, BinaryOp::NeVecI8x16)"), - ("i8x16.lt_s", "makeBinary(s, BinaryOp::LtSVecI8x16)"), - ("i8x16.lt_u", "makeBinary(s, BinaryOp::LtUVecI8x16)"), - ("i8x16.gt_s", "makeBinary(s, BinaryOp::GtSVecI8x16)"), - ("i8x16.gt_u", "makeBinary(s, BinaryOp::GtUVecI8x16)"), - ("i8x16.le_s", "makeBinary(s, BinaryOp::LeSVecI8x16)"), - ("i8x16.le_u", "makeBinary(s, BinaryOp::LeUVecI8x16)"), - ("i8x16.ge_s", "makeBinary(s, BinaryOp::GeSVecI8x16)"), - ("i8x16.ge_u", "makeBinary(s, BinaryOp::GeUVecI8x16)"), - ("i16x8.eq", "makeBinary(s, BinaryOp::EqVecI16x8)"), - ("i16x8.ne", "makeBinary(s, BinaryOp::NeVecI16x8)"), - ("i16x8.lt_s", "makeBinary(s, BinaryOp::LtSVecI16x8)"), - ("i16x8.lt_u", "makeBinary(s, BinaryOp::LtUVecI16x8)"), - ("i16x8.gt_s", "makeBinary(s, BinaryOp::GtSVecI16x8)"), - ("i16x8.gt_u", "makeBinary(s, BinaryOp::GtUVecI16x8)"), - ("i16x8.le_s", "makeBinary(s, BinaryOp::LeSVecI16x8)"), - ("i16x8.le_u", "makeBinary(s, BinaryOp::LeUVecI16x8)"), - ("i16x8.ge_s", "makeBinary(s, BinaryOp::GeSVecI16x8)"), - ("i16x8.ge_u", "makeBinary(s, BinaryOp::GeUVecI16x8)"), - ("i32x4.eq", "makeBinary(s, BinaryOp::EqVecI32x4)"), - ("i32x4.ne", "makeBinary(s, BinaryOp::NeVecI32x4)"), - ("i32x4.lt_s", "makeBinary(s, BinaryOp::LtSVecI32x4)"), - ("i32x4.lt_u", "makeBinary(s, BinaryOp::LtUVecI32x4)"), - ("i32x4.gt_s", "makeBinary(s, BinaryOp::GtSVecI32x4)"), - ("i32x4.gt_u", "makeBinary(s, BinaryOp::GtUVecI32x4)"), - ("i32x4.le_s", "makeBinary(s, BinaryOp::LeSVecI32x4)"), - ("i32x4.le_u", "makeBinary(s, BinaryOp::LeUVecI32x4)"), - ("i32x4.ge_s", "makeBinary(s, BinaryOp::GeSVecI32x4)"), - ("i32x4.ge_u", "makeBinary(s, BinaryOp::GeUVecI32x4)"), - ("i64x2.eq", "makeBinary(s, BinaryOp::EqVecI64x2)"), - ("i64x2.ne", "makeBinary(s, BinaryOp::NeVecI64x2)"), - ("i64x2.lt_s", "makeBinary(s, BinaryOp::LtSVecI64x2)"), - ("i64x2.gt_s", "makeBinary(s, BinaryOp::GtSVecI64x2)"), - ("i64x2.le_s", "makeBinary(s, BinaryOp::LeSVecI64x2)"), - ("i64x2.ge_s", "makeBinary(s, BinaryOp::GeSVecI64x2)"), - ("f32x4.eq", "makeBinary(s, BinaryOp::EqVecF32x4)"), - ("f32x4.ne", "makeBinary(s, BinaryOp::NeVecF32x4)"), - ("f32x4.lt", "makeBinary(s, BinaryOp::LtVecF32x4)"), - ("f32x4.gt", "makeBinary(s, BinaryOp::GtVecF32x4)"), - ("f32x4.le", "makeBinary(s, BinaryOp::LeVecF32x4)"), - ("f32x4.ge", "makeBinary(s, BinaryOp::GeVecF32x4)"), - ("f64x2.eq", "makeBinary(s, BinaryOp::EqVecF64x2)"), - ("f64x2.ne", "makeBinary(s, BinaryOp::NeVecF64x2)"), - ("f64x2.lt", "makeBinary(s, BinaryOp::LtVecF64x2)"), - ("f64x2.gt", "makeBinary(s, BinaryOp::GtVecF64x2)"), - ("f64x2.le", "makeBinary(s, BinaryOp::LeVecF64x2)"), - ("f64x2.ge", "makeBinary(s, BinaryOp::GeVecF64x2)"), - ("v128.not", "makeUnary(s, UnaryOp::NotVec128)"), - ("v128.and", "makeBinary(s, BinaryOp::AndVec128)"), - ("v128.or", "makeBinary(s, BinaryOp::OrVec128)"), - ("v128.xor", "makeBinary(s, BinaryOp::XorVec128)"), - ("v128.andnot", "makeBinary(s, BinaryOp::AndNotVec128)"), - ("v128.any_true", "makeUnary(s, UnaryOp::AnyTrueVec128)"), - ("v128.bitselect", "makeSIMDTernary(s, SIMDTernaryOp::Bitselect)"), - ("v128.load8_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load8LaneVec128, 1)"), - ("v128.load16_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load16LaneVec128, 2)"), - ("v128.load32_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load32LaneVec128, 4)"), - ("v128.load64_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load64LaneVec128, 8)"), - ("v128.store8_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store8LaneVec128, 1)"), - ("v128.store16_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store16LaneVec128, 2)"), - ("v128.store32_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store32LaneVec128, 4)"), - ("v128.store64_lane", "makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store64LaneVec128, 8)"), - ("i8x16.popcnt", "makeUnary(s, UnaryOp::PopcntVecI8x16)"), - ("i8x16.abs", "makeUnary(s, UnaryOp::AbsVecI8x16)"), - ("i8x16.neg", "makeUnary(s, UnaryOp::NegVecI8x16)"), - ("i8x16.all_true", "makeUnary(s, UnaryOp::AllTrueVecI8x16)"), - ("i8x16.bitmask", "makeUnary(s, UnaryOp::BitmaskVecI8x16)"), - ("i8x16.shl", "makeSIMDShift(s, SIMDShiftOp::ShlVecI8x16)"), - ("i8x16.shr_s", "makeSIMDShift(s, SIMDShiftOp::ShrSVecI8x16)"), - ("i8x16.shr_u", "makeSIMDShift(s, SIMDShiftOp::ShrUVecI8x16)"), - ("i8x16.add", "makeBinary(s, BinaryOp::AddVecI8x16)"), - ("i8x16.add_sat_s", "makeBinary(s, BinaryOp::AddSatSVecI8x16)"), - ("i8x16.add_sat_u", "makeBinary(s, BinaryOp::AddSatUVecI8x16)"), - ("i8x16.sub", "makeBinary(s, BinaryOp::SubVecI8x16)"), - ("i8x16.sub_sat_s", "makeBinary(s, BinaryOp::SubSatSVecI8x16)"), - ("i8x16.sub_sat_u", "makeBinary(s, BinaryOp::SubSatUVecI8x16)"), - ("i8x16.min_s", "makeBinary(s, BinaryOp::MinSVecI8x16)"), - ("i8x16.min_u", "makeBinary(s, BinaryOp::MinUVecI8x16)"), - ("i8x16.max_s", "makeBinary(s, BinaryOp::MaxSVecI8x16)"), - ("i8x16.max_u", "makeBinary(s, BinaryOp::MaxUVecI8x16)"), - ("i8x16.avgr_u", "makeBinary(s, BinaryOp::AvgrUVecI8x16)"), - ("i16x8.abs", "makeUnary(s, UnaryOp::AbsVecI16x8)"), - ("i16x8.neg", "makeUnary(s, UnaryOp::NegVecI16x8)"), - ("i16x8.all_true", "makeUnary(s, UnaryOp::AllTrueVecI16x8)"), - ("i16x8.bitmask", "makeUnary(s, UnaryOp::BitmaskVecI16x8)"), - ("i16x8.shl", "makeSIMDShift(s, SIMDShiftOp::ShlVecI16x8)"), - ("i16x8.shr_s", "makeSIMDShift(s, SIMDShiftOp::ShrSVecI16x8)"), - ("i16x8.shr_u", "makeSIMDShift(s, SIMDShiftOp::ShrUVecI16x8)"), - ("i16x8.add", "makeBinary(s, BinaryOp::AddVecI16x8)"), - ("i16x8.add_sat_s", "makeBinary(s, BinaryOp::AddSatSVecI16x8)"), - ("i16x8.add_sat_u", "makeBinary(s, BinaryOp::AddSatUVecI16x8)"), - ("i16x8.sub", "makeBinary(s, BinaryOp::SubVecI16x8)"), - ("i16x8.sub_sat_s", "makeBinary(s, BinaryOp::SubSatSVecI16x8)"), - ("i16x8.sub_sat_u", "makeBinary(s, BinaryOp::SubSatUVecI16x8)"), - ("i16x8.mul", "makeBinary(s, BinaryOp::MulVecI16x8)"), - ("i16x8.min_s", "makeBinary(s, BinaryOp::MinSVecI16x8)"), - ("i16x8.min_u", "makeBinary(s, BinaryOp::MinUVecI16x8)"), - ("i16x8.max_s", "makeBinary(s, BinaryOp::MaxSVecI16x8)"), - ("i16x8.max_u", "makeBinary(s, BinaryOp::MaxUVecI16x8)"), - ("i16x8.avgr_u", "makeBinary(s, BinaryOp::AvgrUVecI16x8)"), - ("i16x8.q15mulr_sat_s", "makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8)"), - ("i16x8.extmul_low_i8x16_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI16x8)"), - ("i16x8.extmul_high_i8x16_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI16x8)"), - ("i16x8.extmul_low_i8x16_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI16x8)"), - ("i16x8.extmul_high_i8x16_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI16x8)"), - ("i32x4.abs", "makeUnary(s, UnaryOp::AbsVecI32x4)"), - ("i32x4.neg", "makeUnary(s, UnaryOp::NegVecI32x4)"), - ("i32x4.all_true", "makeUnary(s, UnaryOp::AllTrueVecI32x4)"), - ("i32x4.bitmask", "makeUnary(s, UnaryOp::BitmaskVecI32x4)"), - ("i32x4.shl", "makeSIMDShift(s, SIMDShiftOp::ShlVecI32x4)"), - ("i32x4.shr_s", "makeSIMDShift(s, SIMDShiftOp::ShrSVecI32x4)"), - ("i32x4.shr_u", "makeSIMDShift(s, SIMDShiftOp::ShrUVecI32x4)"), - ("i32x4.add", "makeBinary(s, BinaryOp::AddVecI32x4)"), - ("i32x4.sub", "makeBinary(s, BinaryOp::SubVecI32x4)"), - ("i32x4.mul", "makeBinary(s, BinaryOp::MulVecI32x4)"), - ("i32x4.min_s", "makeBinary(s, BinaryOp::MinSVecI32x4)"), - ("i32x4.min_u", "makeBinary(s, BinaryOp::MinUVecI32x4)"), - ("i32x4.max_s", "makeBinary(s, BinaryOp::MaxSVecI32x4)"), - ("i32x4.max_u", "makeBinary(s, BinaryOp::MaxUVecI32x4)"), - ("i32x4.dot_i16x8_s", "makeBinary(s, BinaryOp::DotSVecI16x8ToVecI32x4)"), - ("i32x4.extmul_low_i16x8_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI32x4)"), - ("i32x4.extmul_high_i16x8_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI32x4)"), - ("i32x4.extmul_low_i16x8_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI32x4)"), - ("i32x4.extmul_high_i16x8_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI32x4)"), - ("i64x2.abs", "makeUnary(s, UnaryOp::AbsVecI64x2)"), - ("i64x2.neg", "makeUnary(s, UnaryOp::NegVecI64x2)"), - ("i64x2.all_true", "makeUnary(s, UnaryOp::AllTrueVecI64x2)"), - ("i64x2.bitmask", "makeUnary(s, UnaryOp::BitmaskVecI64x2)"), - ("i64x2.shl", "makeSIMDShift(s, SIMDShiftOp::ShlVecI64x2)"), - ("i64x2.shr_s", "makeSIMDShift(s, SIMDShiftOp::ShrSVecI64x2)"), - ("i64x2.shr_u", "makeSIMDShift(s, SIMDShiftOp::ShrUVecI64x2)"), - ("i64x2.add", "makeBinary(s, BinaryOp::AddVecI64x2)"), - ("i64x2.sub", "makeBinary(s, BinaryOp::SubVecI64x2)"), - ("i64x2.mul", "makeBinary(s, BinaryOp::MulVecI64x2)"), - ("i64x2.extmul_low_i32x4_s", "makeBinary(s, BinaryOp::ExtMulLowSVecI64x2)"), - ("i64x2.extmul_high_i32x4_s", "makeBinary(s, BinaryOp::ExtMulHighSVecI64x2)"), - ("i64x2.extmul_low_i32x4_u", "makeBinary(s, BinaryOp::ExtMulLowUVecI64x2)"), - ("i64x2.extmul_high_i32x4_u", "makeBinary(s, BinaryOp::ExtMulHighUVecI64x2)"), - ("f32x4.abs", "makeUnary(s, UnaryOp::AbsVecF32x4)"), - ("f32x4.neg", "makeUnary(s, UnaryOp::NegVecF32x4)"), - ("f32x4.sqrt", "makeUnary(s, UnaryOp::SqrtVecF32x4)"), - ("f32x4.add", "makeBinary(s, BinaryOp::AddVecF32x4)"), - ("f32x4.sub", "makeBinary(s, BinaryOp::SubVecF32x4)"), - ("f32x4.mul", "makeBinary(s, BinaryOp::MulVecF32x4)"), - ("f32x4.div", "makeBinary(s, BinaryOp::DivVecF32x4)"), - ("f32x4.min", "makeBinary(s, BinaryOp::MinVecF32x4)"), - ("f32x4.max", "makeBinary(s, BinaryOp::MaxVecF32x4)"), - ("f32x4.pmin", "makeBinary(s, BinaryOp::PMinVecF32x4)"), - ("f32x4.pmax", "makeBinary(s, BinaryOp::PMaxVecF32x4)"), - ("f32x4.ceil", "makeUnary(s, UnaryOp::CeilVecF32x4)"), - ("f32x4.floor", "makeUnary(s, UnaryOp::FloorVecF32x4)"), - ("f32x4.trunc", "makeUnary(s, UnaryOp::TruncVecF32x4)"), - ("f32x4.nearest", "makeUnary(s, UnaryOp::NearestVecF32x4)"), - ("f64x2.abs", "makeUnary(s, UnaryOp::AbsVecF64x2)"), - ("f64x2.neg", "makeUnary(s, UnaryOp::NegVecF64x2)"), - ("f64x2.sqrt", "makeUnary(s, UnaryOp::SqrtVecF64x2)"), - ("f64x2.add", "makeBinary(s, BinaryOp::AddVecF64x2)"), - ("f64x2.sub", "makeBinary(s, BinaryOp::SubVecF64x2)"), - ("f64x2.mul", "makeBinary(s, BinaryOp::MulVecF64x2)"), - ("f64x2.div", "makeBinary(s, BinaryOp::DivVecF64x2)"), - ("f64x2.min", "makeBinary(s, BinaryOp::MinVecF64x2)"), - ("f64x2.max", "makeBinary(s, BinaryOp::MaxVecF64x2)"), - ("f64x2.pmin", "makeBinary(s, BinaryOp::PMinVecF64x2)"), - ("f64x2.pmax", "makeBinary(s, BinaryOp::PMaxVecF64x2)"), - ("f64x2.ceil", "makeUnary(s, UnaryOp::CeilVecF64x2)"), - ("f64x2.floor", "makeUnary(s, UnaryOp::FloorVecF64x2)"), - ("f64x2.trunc", "makeUnary(s, UnaryOp::TruncVecF64x2)"), - ("f64x2.nearest", "makeUnary(s, UnaryOp::NearestVecF64x2)"), - ("i32x4.trunc_sat_f32x4_s", "makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4)"), - ("i32x4.trunc_sat_f32x4_u", "makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4)"), - ("f32x4.convert_i32x4_s", "makeUnary(s, UnaryOp::ConvertSVecI32x4ToVecF32x4)"), - ("f32x4.convert_i32x4_u", "makeUnary(s, UnaryOp::ConvertUVecI32x4ToVecF32x4)"), - ("v128.load8_splat", "makeSIMDLoad(s, SIMDLoadOp::Load8SplatVec128, 1)"), - ("v128.load16_splat", "makeSIMDLoad(s, SIMDLoadOp::Load16SplatVec128, 2)"), - ("v128.load32_splat", "makeSIMDLoad(s, SIMDLoadOp::Load32SplatVec128, 4)"), - ("v128.load64_splat", "makeSIMDLoad(s, SIMDLoadOp::Load64SplatVec128, 8)"), - ("v128.load8x8_s", "makeSIMDLoad(s, SIMDLoadOp::Load8x8SVec128, 8)"), - ("v128.load8x8_u", "makeSIMDLoad(s, SIMDLoadOp::Load8x8UVec128, 8)"), - ("v128.load16x4_s", "makeSIMDLoad(s, SIMDLoadOp::Load16x4SVec128, 8)"), - ("v128.load16x4_u", "makeSIMDLoad(s, SIMDLoadOp::Load16x4UVec128, 8)"), - ("v128.load32x2_s", "makeSIMDLoad(s, SIMDLoadOp::Load32x2SVec128, 8)"), - ("v128.load32x2_u", "makeSIMDLoad(s, SIMDLoadOp::Load32x2UVec128, 8)"), - ("v128.load32_zero", "makeSIMDLoad(s, SIMDLoadOp::Load32ZeroVec128, 4)"), - ("v128.load64_zero", "makeSIMDLoad(s, SIMDLoadOp::Load64ZeroVec128, 8)"), - ("i8x16.narrow_i16x8_s", "makeBinary(s, BinaryOp::NarrowSVecI16x8ToVecI8x16)"), - ("i8x16.narrow_i16x8_u", "makeBinary(s, BinaryOp::NarrowUVecI16x8ToVecI8x16)"), - ("i16x8.narrow_i32x4_s", "makeBinary(s, BinaryOp::NarrowSVecI32x4ToVecI16x8)"), - ("i16x8.narrow_i32x4_u", "makeBinary(s, BinaryOp::NarrowUVecI32x4ToVecI16x8)"), - ("i16x8.extend_low_i8x16_s", "makeUnary(s, UnaryOp::ExtendLowSVecI8x16ToVecI16x8)"), - ("i16x8.extend_high_i8x16_s", "makeUnary(s, UnaryOp::ExtendHighSVecI8x16ToVecI16x8)"), - ("i16x8.extend_low_i8x16_u", "makeUnary(s, UnaryOp::ExtendLowUVecI8x16ToVecI16x8)"), - ("i16x8.extend_high_i8x16_u", "makeUnary(s, UnaryOp::ExtendHighUVecI8x16ToVecI16x8)"), - ("i32x4.extend_low_i16x8_s", "makeUnary(s, UnaryOp::ExtendLowSVecI16x8ToVecI32x4)"), - ("i32x4.extend_high_i16x8_s", "makeUnary(s, UnaryOp::ExtendHighSVecI16x8ToVecI32x4)"), - ("i32x4.extend_low_i16x8_u", "makeUnary(s, UnaryOp::ExtendLowUVecI16x8ToVecI32x4)"), - ("i32x4.extend_high_i16x8_u", "makeUnary(s, UnaryOp::ExtendHighUVecI16x8ToVecI32x4)"), - ("i64x2.extend_low_i32x4_s", "makeUnary(s, UnaryOp::ExtendLowSVecI32x4ToVecI64x2)"), - ("i64x2.extend_high_i32x4_s", "makeUnary(s, UnaryOp::ExtendHighSVecI32x4ToVecI64x2)"), - ("i64x2.extend_low_i32x4_u", "makeUnary(s, UnaryOp::ExtendLowUVecI32x4ToVecI64x2)"), - ("i64x2.extend_high_i32x4_u", "makeUnary(s, UnaryOp::ExtendHighUVecI32x4ToVecI64x2)"), - ("i8x16.swizzle", "makeBinary(s, BinaryOp::SwizzleVecI8x16)"), - ("i16x8.extadd_pairwise_i8x16_s", "makeUnary(s, UnaryOp::ExtAddPairwiseSVecI8x16ToI16x8)"), - ("i16x8.extadd_pairwise_i8x16_u", "makeUnary(s, UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8)"), - ("i32x4.extadd_pairwise_i16x8_s", "makeUnary(s, UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4)"), - ("i32x4.extadd_pairwise_i16x8_u", "makeUnary(s, UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4)"), - ("f64x2.convert_low_i32x4_s", "makeUnary(s, UnaryOp::ConvertLowSVecI32x4ToVecF64x2)"), - ("f64x2.convert_low_i32x4_u", "makeUnary(s, UnaryOp::ConvertLowUVecI32x4ToVecF64x2)"), - ("i32x4.trunc_sat_f64x2_s_zero", "makeUnary(s, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4)"), - ("i32x4.trunc_sat_f64x2_u_zero", "makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4)"), - ("f32x4.demote_f64x2_zero", "makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4)"), - ("f64x2.promote_low_f32x4", "makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2)"), + ("v128.load", "makeLoad(Type::v128, /*signed=*/false, 16, /*isAtomic=*/false)"), + ("v128.store", "makeStore(Type::v128, 16, /*isAtomic=*/false)"), + ("v128.const", "makeConst(Type::v128)"), + ("i8x16.shuffle", "makeSIMDShuffle()"), + ("i8x16.splat", "makeUnary(UnaryOp::SplatVecI8x16)"), + ("i8x16.extract_lane_s", "makeSIMDExtract(SIMDExtractOp::ExtractLaneSVecI8x16, 16)"), + ("i8x16.extract_lane_u", "makeSIMDExtract(SIMDExtractOp::ExtractLaneUVecI8x16, 16)"), + ("i8x16.replace_lane", "makeSIMDReplace(SIMDReplaceOp::ReplaceLaneVecI8x16, 16)"), + ("i16x8.splat", "makeUnary(UnaryOp::SplatVecI16x8)"), + ("i16x8.extract_lane_s", "makeSIMDExtract(SIMDExtractOp::ExtractLaneSVecI16x8, 8)"), + ("i16x8.extract_lane_u", "makeSIMDExtract(SIMDExtractOp::ExtractLaneUVecI16x8, 8)"), + ("i16x8.replace_lane", "makeSIMDReplace(SIMDReplaceOp::ReplaceLaneVecI16x8, 8)"), + ("i32x4.splat", "makeUnary(UnaryOp::SplatVecI32x4)"), + ("i32x4.extract_lane", "makeSIMDExtract(SIMDExtractOp::ExtractLaneVecI32x4, 4)"), + ("i32x4.replace_lane", "makeSIMDReplace(SIMDReplaceOp::ReplaceLaneVecI32x4, 4)"), + ("i64x2.splat", "makeUnary(UnaryOp::SplatVecI64x2)"), + ("i64x2.extract_lane", "makeSIMDExtract(SIMDExtractOp::ExtractLaneVecI64x2, 2)"), + ("i64x2.replace_lane", "makeSIMDReplace(SIMDReplaceOp::ReplaceLaneVecI64x2, 2)"), + ("f32x4.splat", "makeUnary(UnaryOp::SplatVecF32x4)"), + ("f32x4.extract_lane", "makeSIMDExtract(SIMDExtractOp::ExtractLaneVecF32x4, 4)"), + ("f32x4.replace_lane", "makeSIMDReplace(SIMDReplaceOp::ReplaceLaneVecF32x4, 4)"), + ("f64x2.splat", "makeUnary(UnaryOp::SplatVecF64x2)"), + ("f64x2.extract_lane", "makeSIMDExtract(SIMDExtractOp::ExtractLaneVecF64x2, 2)"), + ("f64x2.replace_lane", "makeSIMDReplace(SIMDReplaceOp::ReplaceLaneVecF64x2, 2)"), + ("i8x16.eq", "makeBinary(BinaryOp::EqVecI8x16)"), + ("i8x16.ne", "makeBinary(BinaryOp::NeVecI8x16)"), + ("i8x16.lt_s", "makeBinary(BinaryOp::LtSVecI8x16)"), + ("i8x16.lt_u", "makeBinary(BinaryOp::LtUVecI8x16)"), + ("i8x16.gt_s", "makeBinary(BinaryOp::GtSVecI8x16)"), + ("i8x16.gt_u", "makeBinary(BinaryOp::GtUVecI8x16)"), + ("i8x16.le_s", "makeBinary(BinaryOp::LeSVecI8x16)"), + ("i8x16.le_u", "makeBinary(BinaryOp::LeUVecI8x16)"), + ("i8x16.ge_s", "makeBinary(BinaryOp::GeSVecI8x16)"), + ("i8x16.ge_u", "makeBinary(BinaryOp::GeUVecI8x16)"), + ("i16x8.eq", "makeBinary(BinaryOp::EqVecI16x8)"), + ("i16x8.ne", "makeBinary(BinaryOp::NeVecI16x8)"), + ("i16x8.lt_s", "makeBinary(BinaryOp::LtSVecI16x8)"), + ("i16x8.lt_u", "makeBinary(BinaryOp::LtUVecI16x8)"), + ("i16x8.gt_s", "makeBinary(BinaryOp::GtSVecI16x8)"), + ("i16x8.gt_u", "makeBinary(BinaryOp::GtUVecI16x8)"), + ("i16x8.le_s", "makeBinary(BinaryOp::LeSVecI16x8)"), + ("i16x8.le_u", "makeBinary(BinaryOp::LeUVecI16x8)"), + ("i16x8.ge_s", "makeBinary(BinaryOp::GeSVecI16x8)"), + ("i16x8.ge_u", "makeBinary(BinaryOp::GeUVecI16x8)"), + ("i32x4.eq", "makeBinary(BinaryOp::EqVecI32x4)"), + ("i32x4.ne", "makeBinary(BinaryOp::NeVecI32x4)"), + ("i32x4.lt_s", "makeBinary(BinaryOp::LtSVecI32x4)"), + ("i32x4.lt_u", "makeBinary(BinaryOp::LtUVecI32x4)"), + ("i32x4.gt_s", "makeBinary(BinaryOp::GtSVecI32x4)"), + ("i32x4.gt_u", "makeBinary(BinaryOp::GtUVecI32x4)"), + ("i32x4.le_s", "makeBinary(BinaryOp::LeSVecI32x4)"), + ("i32x4.le_u", "makeBinary(BinaryOp::LeUVecI32x4)"), + ("i32x4.ge_s", "makeBinary(BinaryOp::GeSVecI32x4)"), + ("i32x4.ge_u", "makeBinary(BinaryOp::GeUVecI32x4)"), + ("i64x2.eq", "makeBinary(BinaryOp::EqVecI64x2)"), + ("i64x2.ne", "makeBinary(BinaryOp::NeVecI64x2)"), + ("i64x2.lt_s", "makeBinary(BinaryOp::LtSVecI64x2)"), + ("i64x2.gt_s", "makeBinary(BinaryOp::GtSVecI64x2)"), + ("i64x2.le_s", "makeBinary(BinaryOp::LeSVecI64x2)"), + ("i64x2.ge_s", "makeBinary(BinaryOp::GeSVecI64x2)"), + ("f32x4.eq", "makeBinary(BinaryOp::EqVecF32x4)"), + ("f32x4.ne", "makeBinary(BinaryOp::NeVecF32x4)"), + ("f32x4.lt", "makeBinary(BinaryOp::LtVecF32x4)"), + ("f32x4.gt", "makeBinary(BinaryOp::GtVecF32x4)"), + ("f32x4.le", "makeBinary(BinaryOp::LeVecF32x4)"), + ("f32x4.ge", "makeBinary(BinaryOp::GeVecF32x4)"), + ("f64x2.eq", "makeBinary(BinaryOp::EqVecF64x2)"), + ("f64x2.ne", "makeBinary(BinaryOp::NeVecF64x2)"), + ("f64x2.lt", "makeBinary(BinaryOp::LtVecF64x2)"), + ("f64x2.gt", "makeBinary(BinaryOp::GtVecF64x2)"), + ("f64x2.le", "makeBinary(BinaryOp::LeVecF64x2)"), + ("f64x2.ge", "makeBinary(BinaryOp::GeVecF64x2)"), + ("v128.not", "makeUnary(UnaryOp::NotVec128)"), + ("v128.and", "makeBinary(BinaryOp::AndVec128)"), + ("v128.or", "makeBinary(BinaryOp::OrVec128)"), + ("v128.xor", "makeBinary(BinaryOp::XorVec128)"), + ("v128.andnot", "makeBinary(BinaryOp::AndNotVec128)"), + ("v128.any_true", "makeUnary(UnaryOp::AnyTrueVec128)"), + ("v128.bitselect", "makeSIMDTernary(SIMDTernaryOp::Bitselect)"), + ("v128.load8_lane", "makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp::Load8LaneVec128, 1)"), + ("v128.load16_lane", "makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp::Load16LaneVec128, 2)"), + ("v128.load32_lane", "makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp::Load32LaneVec128, 4)"), + ("v128.load64_lane", "makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp::Load64LaneVec128, 8)"), + ("v128.store8_lane", "makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp::Store8LaneVec128, 1)"), + ("v128.store16_lane", "makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp::Store16LaneVec128, 2)"), + ("v128.store32_lane", "makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp::Store32LaneVec128, 4)"), + ("v128.store64_lane", "makeSIMDLoadStoreLane(SIMDLoadStoreLaneOp::Store64LaneVec128, 8)"), + ("i8x16.popcnt", "makeUnary(UnaryOp::PopcntVecI8x16)"), + ("i8x16.abs", "makeUnary(UnaryOp::AbsVecI8x16)"), + ("i8x16.neg", "makeUnary(UnaryOp::NegVecI8x16)"), + ("i8x16.all_true", "makeUnary(UnaryOp::AllTrueVecI8x16)"), + ("i8x16.bitmask", "makeUnary(UnaryOp::BitmaskVecI8x16)"), + ("i8x16.shl", "makeSIMDShift(SIMDShiftOp::ShlVecI8x16)"), + ("i8x16.shr_s", "makeSIMDShift(SIMDShiftOp::ShrSVecI8x16)"), + ("i8x16.shr_u", "makeSIMDShift(SIMDShiftOp::ShrUVecI8x16)"), + ("i8x16.add", "makeBinary(BinaryOp::AddVecI8x16)"), + ("i8x16.add_sat_s", "makeBinary(BinaryOp::AddSatSVecI8x16)"), + ("i8x16.add_sat_u", "makeBinary(BinaryOp::AddSatUVecI8x16)"), + ("i8x16.sub", "makeBinary(BinaryOp::SubVecI8x16)"), + ("i8x16.sub_sat_s", "makeBinary(BinaryOp::SubSatSVecI8x16)"), + ("i8x16.sub_sat_u", "makeBinary(BinaryOp::SubSatUVecI8x16)"), + ("i8x16.min_s", "makeBinary(BinaryOp::MinSVecI8x16)"), + ("i8x16.min_u", "makeBinary(BinaryOp::MinUVecI8x16)"), + ("i8x16.max_s", "makeBinary(BinaryOp::MaxSVecI8x16)"), + ("i8x16.max_u", "makeBinary(BinaryOp::MaxUVecI8x16)"), + ("i8x16.avgr_u", "makeBinary(BinaryOp::AvgrUVecI8x16)"), + ("i16x8.abs", "makeUnary(UnaryOp::AbsVecI16x8)"), + ("i16x8.neg", "makeUnary(UnaryOp::NegVecI16x8)"), + ("i16x8.all_true", "makeUnary(UnaryOp::AllTrueVecI16x8)"), + ("i16x8.bitmask", "makeUnary(UnaryOp::BitmaskVecI16x8)"), + ("i16x8.shl", "makeSIMDShift(SIMDShiftOp::ShlVecI16x8)"), + ("i16x8.shr_s", "makeSIMDShift(SIMDShiftOp::ShrSVecI16x8)"), + ("i16x8.shr_u", "makeSIMDShift(SIMDShiftOp::ShrUVecI16x8)"), + ("i16x8.add", "makeBinary(BinaryOp::AddVecI16x8)"), + ("i16x8.add_sat_s", "makeBinary(BinaryOp::AddSatSVecI16x8)"), + ("i16x8.add_sat_u", "makeBinary(BinaryOp::AddSatUVecI16x8)"), + ("i16x8.sub", "makeBinary(BinaryOp::SubVecI16x8)"), + ("i16x8.sub_sat_s", "makeBinary(BinaryOp::SubSatSVecI16x8)"), + ("i16x8.sub_sat_u", "makeBinary(BinaryOp::SubSatUVecI16x8)"), + ("i16x8.mul", "makeBinary(BinaryOp::MulVecI16x8)"), + ("i16x8.min_s", "makeBinary(BinaryOp::MinSVecI16x8)"), + ("i16x8.min_u", "makeBinary(BinaryOp::MinUVecI16x8)"), + ("i16x8.max_s", "makeBinary(BinaryOp::MaxSVecI16x8)"), + ("i16x8.max_u", "makeBinary(BinaryOp::MaxUVecI16x8)"), + ("i16x8.avgr_u", "makeBinary(BinaryOp::AvgrUVecI16x8)"), + ("i16x8.q15mulr_sat_s", "makeBinary(BinaryOp::Q15MulrSatSVecI16x8)"), + ("i16x8.extmul_low_i8x16_s", "makeBinary(BinaryOp::ExtMulLowSVecI16x8)"), + ("i16x8.extmul_high_i8x16_s", "makeBinary(BinaryOp::ExtMulHighSVecI16x8)"), + ("i16x8.extmul_low_i8x16_u", "makeBinary(BinaryOp::ExtMulLowUVecI16x8)"), + ("i16x8.extmul_high_i8x16_u", "makeBinary(BinaryOp::ExtMulHighUVecI16x8)"), + ("i32x4.abs", "makeUnary(UnaryOp::AbsVecI32x4)"), + ("i32x4.neg", "makeUnary(UnaryOp::NegVecI32x4)"), + ("i32x4.all_true", "makeUnary(UnaryOp::AllTrueVecI32x4)"), + ("i32x4.bitmask", "makeUnary(UnaryOp::BitmaskVecI32x4)"), + ("i32x4.shl", "makeSIMDShift(SIMDShiftOp::ShlVecI32x4)"), + ("i32x4.shr_s", "makeSIMDShift(SIMDShiftOp::ShrSVecI32x4)"), + ("i32x4.shr_u", "makeSIMDShift(SIMDShiftOp::ShrUVecI32x4)"), + ("i32x4.add", "makeBinary(BinaryOp::AddVecI32x4)"), + ("i32x4.sub", "makeBinary(BinaryOp::SubVecI32x4)"), + ("i32x4.mul", "makeBinary(BinaryOp::MulVecI32x4)"), + ("i32x4.min_s", "makeBinary(BinaryOp::MinSVecI32x4)"), + ("i32x4.min_u", "makeBinary(BinaryOp::MinUVecI32x4)"), + ("i32x4.max_s", "makeBinary(BinaryOp::MaxSVecI32x4)"), + ("i32x4.max_u", "makeBinary(BinaryOp::MaxUVecI32x4)"), + ("i32x4.dot_i16x8_s", "makeBinary(BinaryOp::DotSVecI16x8ToVecI32x4)"), + ("i32x4.extmul_low_i16x8_s", "makeBinary(BinaryOp::ExtMulLowSVecI32x4)"), + ("i32x4.extmul_high_i16x8_s", "makeBinary(BinaryOp::ExtMulHighSVecI32x4)"), + ("i32x4.extmul_low_i16x8_u", "makeBinary(BinaryOp::ExtMulLowUVecI32x4)"), + ("i32x4.extmul_high_i16x8_u", "makeBinary(BinaryOp::ExtMulHighUVecI32x4)"), + ("i64x2.abs", "makeUnary(UnaryOp::AbsVecI64x2)"), + ("i64x2.neg", "makeUnary(UnaryOp::NegVecI64x2)"), + ("i64x2.all_true", "makeUnary(UnaryOp::AllTrueVecI64x2)"), + ("i64x2.bitmask", "makeUnary(UnaryOp::BitmaskVecI64x2)"), + ("i64x2.shl", "makeSIMDShift(SIMDShiftOp::ShlVecI64x2)"), + ("i64x2.shr_s", "makeSIMDShift(SIMDShiftOp::ShrSVecI64x2)"), + ("i64x2.shr_u", "makeSIMDShift(SIMDShiftOp::ShrUVecI64x2)"), + ("i64x2.add", "makeBinary(BinaryOp::AddVecI64x2)"), + ("i64x2.sub", "makeBinary(BinaryOp::SubVecI64x2)"), + ("i64x2.mul", "makeBinary(BinaryOp::MulVecI64x2)"), + ("i64x2.extmul_low_i32x4_s", "makeBinary(BinaryOp::ExtMulLowSVecI64x2)"), + ("i64x2.extmul_high_i32x4_s", "makeBinary(BinaryOp::ExtMulHighSVecI64x2)"), + ("i64x2.extmul_low_i32x4_u", "makeBinary(BinaryOp::ExtMulLowUVecI64x2)"), + ("i64x2.extmul_high_i32x4_u", "makeBinary(BinaryOp::ExtMulHighUVecI64x2)"), + ("f32x4.abs", "makeUnary(UnaryOp::AbsVecF32x4)"), + ("f32x4.neg", "makeUnary(UnaryOp::NegVecF32x4)"), + ("f32x4.sqrt", "makeUnary(UnaryOp::SqrtVecF32x4)"), + ("f32x4.add", "makeBinary(BinaryOp::AddVecF32x4)"), + ("f32x4.sub", "makeBinary(BinaryOp::SubVecF32x4)"), + ("f32x4.mul", "makeBinary(BinaryOp::MulVecF32x4)"), + ("f32x4.div", "makeBinary(BinaryOp::DivVecF32x4)"), + ("f32x4.min", "makeBinary(BinaryOp::MinVecF32x4)"), + ("f32x4.max", "makeBinary(BinaryOp::MaxVecF32x4)"), + ("f32x4.pmin", "makeBinary(BinaryOp::PMinVecF32x4)"), + ("f32x4.pmax", "makeBinary(BinaryOp::PMaxVecF32x4)"), + ("f32x4.ceil", "makeUnary(UnaryOp::CeilVecF32x4)"), + ("f32x4.floor", "makeUnary(UnaryOp::FloorVecF32x4)"), + ("f32x4.trunc", "makeUnary(UnaryOp::TruncVecF32x4)"), + ("f32x4.nearest", "makeUnary(UnaryOp::NearestVecF32x4)"), + ("f64x2.abs", "makeUnary(UnaryOp::AbsVecF64x2)"), + ("f64x2.neg", "makeUnary(UnaryOp::NegVecF64x2)"), + ("f64x2.sqrt", "makeUnary(UnaryOp::SqrtVecF64x2)"), + ("f64x2.add", "makeBinary(BinaryOp::AddVecF64x2)"), + ("f64x2.sub", "makeBinary(BinaryOp::SubVecF64x2)"), + ("f64x2.mul", "makeBinary(BinaryOp::MulVecF64x2)"), + ("f64x2.div", "makeBinary(BinaryOp::DivVecF64x2)"), + ("f64x2.min", "makeBinary(BinaryOp::MinVecF64x2)"), + ("f64x2.max", "makeBinary(BinaryOp::MaxVecF64x2)"), + ("f64x2.pmin", "makeBinary(BinaryOp::PMinVecF64x2)"), + ("f64x2.pmax", "makeBinary(BinaryOp::PMaxVecF64x2)"), + ("f64x2.ceil", "makeUnary(UnaryOp::CeilVecF64x2)"), + ("f64x2.floor", "makeUnary(UnaryOp::FloorVecF64x2)"), + ("f64x2.trunc", "makeUnary(UnaryOp::TruncVecF64x2)"), + ("f64x2.nearest", "makeUnary(UnaryOp::NearestVecF64x2)"), + ("i32x4.trunc_sat_f32x4_s", "makeUnary(UnaryOp::TruncSatSVecF32x4ToVecI32x4)"), + ("i32x4.trunc_sat_f32x4_u", "makeUnary(UnaryOp::TruncSatUVecF32x4ToVecI32x4)"), + ("f32x4.convert_i32x4_s", "makeUnary(UnaryOp::ConvertSVecI32x4ToVecF32x4)"), + ("f32x4.convert_i32x4_u", "makeUnary(UnaryOp::ConvertUVecI32x4ToVecF32x4)"), + ("v128.load8_splat", "makeSIMDLoad(SIMDLoadOp::Load8SplatVec128, 1)"), + ("v128.load16_splat", "makeSIMDLoad(SIMDLoadOp::Load16SplatVec128, 2)"), + ("v128.load32_splat", "makeSIMDLoad(SIMDLoadOp::Load32SplatVec128, 4)"), + ("v128.load64_splat", "makeSIMDLoad(SIMDLoadOp::Load64SplatVec128, 8)"), + ("v128.load8x8_s", "makeSIMDLoad(SIMDLoadOp::Load8x8SVec128, 8)"), + ("v128.load8x8_u", "makeSIMDLoad(SIMDLoadOp::Load8x8UVec128, 8)"), + ("v128.load16x4_s", "makeSIMDLoad(SIMDLoadOp::Load16x4SVec128, 8)"), + ("v128.load16x4_u", "makeSIMDLoad(SIMDLoadOp::Load16x4UVec128, 8)"), + ("v128.load32x2_s", "makeSIMDLoad(SIMDLoadOp::Load32x2SVec128, 8)"), + ("v128.load32x2_u", "makeSIMDLoad(SIMDLoadOp::Load32x2UVec128, 8)"), + ("v128.load32_zero", "makeSIMDLoad(SIMDLoadOp::Load32ZeroVec128, 4)"), + ("v128.load64_zero", "makeSIMDLoad(SIMDLoadOp::Load64ZeroVec128, 8)"), + ("i8x16.narrow_i16x8_s", "makeBinary(BinaryOp::NarrowSVecI16x8ToVecI8x16)"), + ("i8x16.narrow_i16x8_u", "makeBinary(BinaryOp::NarrowUVecI16x8ToVecI8x16)"), + ("i16x8.narrow_i32x4_s", "makeBinary(BinaryOp::NarrowSVecI32x4ToVecI16x8)"), + ("i16x8.narrow_i32x4_u", "makeBinary(BinaryOp::NarrowUVecI32x4ToVecI16x8)"), + ("i16x8.extend_low_i8x16_s", "makeUnary(UnaryOp::ExtendLowSVecI8x16ToVecI16x8)"), + ("i16x8.extend_high_i8x16_s", "makeUnary(UnaryOp::ExtendHighSVecI8x16ToVecI16x8)"), + ("i16x8.extend_low_i8x16_u", "makeUnary(UnaryOp::ExtendLowUVecI8x16ToVecI16x8)"), + ("i16x8.extend_high_i8x16_u", "makeUnary(UnaryOp::ExtendHighUVecI8x16ToVecI16x8)"), + ("i32x4.extend_low_i16x8_s", "makeUnary(UnaryOp::ExtendLowSVecI16x8ToVecI32x4)"), + ("i32x4.extend_high_i16x8_s", "makeUnary(UnaryOp::ExtendHighSVecI16x8ToVecI32x4)"), + ("i32x4.extend_low_i16x8_u", "makeUnary(UnaryOp::ExtendLowUVecI16x8ToVecI32x4)"), + ("i32x4.extend_high_i16x8_u", "makeUnary(UnaryOp::ExtendHighUVecI16x8ToVecI32x4)"), + ("i64x2.extend_low_i32x4_s", "makeUnary(UnaryOp::ExtendLowSVecI32x4ToVecI64x2)"), + ("i64x2.extend_high_i32x4_s", "makeUnary(UnaryOp::ExtendHighSVecI32x4ToVecI64x2)"), + ("i64x2.extend_low_i32x4_u", "makeUnary(UnaryOp::ExtendLowUVecI32x4ToVecI64x2)"), + ("i64x2.extend_high_i32x4_u", "makeUnary(UnaryOp::ExtendHighUVecI32x4ToVecI64x2)"), + ("i8x16.swizzle", "makeBinary(BinaryOp::SwizzleVecI8x16)"), + ("i16x8.extadd_pairwise_i8x16_s", "makeUnary(UnaryOp::ExtAddPairwiseSVecI8x16ToI16x8)"), + ("i16x8.extadd_pairwise_i8x16_u", "makeUnary(UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8)"), + ("i32x4.extadd_pairwise_i16x8_s", "makeUnary(UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4)"), + ("i32x4.extadd_pairwise_i16x8_u", "makeUnary(UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4)"), + ("f64x2.convert_low_i32x4_s", "makeUnary(UnaryOp::ConvertLowSVecI32x4ToVecF64x2)"), + ("f64x2.convert_low_i32x4_u", "makeUnary(UnaryOp::ConvertLowUVecI32x4ToVecF64x2)"), + ("i32x4.trunc_sat_f64x2_s_zero", "makeUnary(UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4)"), + ("i32x4.trunc_sat_f64x2_u_zero", "makeUnary(UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4)"), + ("f32x4.demote_f64x2_zero", "makeUnary(UnaryOp::DemoteZeroVecF64x2ToVecF32x4)"), + ("f64x2.promote_low_f32x4", "makeUnary(UnaryOp::PromoteLowVecF32x4ToVecF64x2)"), # relaxed SIMD ops - ("i8x16.relaxed_swizzle", "makeBinary(s, BinaryOp::RelaxedSwizzleVecI8x16)"), - ("i32x4.relaxed_trunc_f32x4_s", "makeUnary(s, UnaryOp::RelaxedTruncSVecF32x4ToVecI32x4)"), - ("i32x4.relaxed_trunc_f32x4_u", "makeUnary(s, UnaryOp::RelaxedTruncUVecF32x4ToVecI32x4)"), - ("i32x4.relaxed_trunc_f64x2_s_zero", "makeUnary(s, UnaryOp::RelaxedTruncZeroSVecF64x2ToVecI32x4)"), - ("i32x4.relaxed_trunc_f64x2_u_zero", "makeUnary(s, UnaryOp::RelaxedTruncZeroUVecF64x2ToVecI32x4)"), - ("f32x4.relaxed_fma", "makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF32x4)"), - ("f32x4.relaxed_fms", "makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF32x4)"), - ("f64x2.relaxed_fma", "makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF64x2)"), - ("f64x2.relaxed_fms", "makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF64x2)"), - ("i8x16.laneselect", "makeSIMDTernary(s, SIMDTernaryOp::LaneselectI8x16)"), - ("i16x8.laneselect", "makeSIMDTernary(s, SIMDTernaryOp::LaneselectI16x8)"), - ("i32x4.laneselect", "makeSIMDTernary(s, SIMDTernaryOp::LaneselectI32x4)"), - ("i64x2.laneselect", "makeSIMDTernary(s, SIMDTernaryOp::LaneselectI64x2)"), - ("f32x4.relaxed_min", "makeBinary(s, BinaryOp::RelaxedMinVecF32x4)"), - ("f32x4.relaxed_max", "makeBinary(s, BinaryOp::RelaxedMaxVecF32x4)"), - ("f64x2.relaxed_min", "makeBinary(s, BinaryOp::RelaxedMinVecF64x2)"), - ("f64x2.relaxed_max", "makeBinary(s, BinaryOp::RelaxedMaxVecF64x2)"), - ("i16x8.relaxed_q15mulr_s", "makeBinary(s, BinaryOp::RelaxedQ15MulrSVecI16x8)"), - ("i16x8.dot_i8x16_i7x16_s", "makeBinary(s, BinaryOp::DotI8x16I7x16SToVecI16x8)"), - ("i32x4.dot_i8x16_i7x16_add_s", "makeSIMDTernary(s, SIMDTernaryOp::DotI8x16I7x16AddSToVecI32x4)"), + ("i8x16.relaxed_swizzle", "makeBinary(BinaryOp::RelaxedSwizzleVecI8x16)"), + ("i32x4.relaxed_trunc_f32x4_s", "makeUnary(UnaryOp::RelaxedTruncSVecF32x4ToVecI32x4)"), + ("i32x4.relaxed_trunc_f32x4_u", "makeUnary(UnaryOp::RelaxedTruncUVecF32x4ToVecI32x4)"), + ("i32x4.relaxed_trunc_f64x2_s_zero", "makeUnary(UnaryOp::RelaxedTruncZeroSVecF64x2ToVecI32x4)"), + ("i32x4.relaxed_trunc_f64x2_u_zero", "makeUnary(UnaryOp::RelaxedTruncZeroUVecF64x2ToVecI32x4)"), + ("f32x4.relaxed_fma", "makeSIMDTernary(SIMDTernaryOp::RelaxedFmaVecF32x4)"), + ("f32x4.relaxed_fms", "makeSIMDTernary(SIMDTernaryOp::RelaxedFmsVecF32x4)"), + ("f64x2.relaxed_fma", "makeSIMDTernary(SIMDTernaryOp::RelaxedFmaVecF64x2)"), + ("f64x2.relaxed_fms", "makeSIMDTernary(SIMDTernaryOp::RelaxedFmsVecF64x2)"), + ("i8x16.laneselect", "makeSIMDTernary(SIMDTernaryOp::LaneselectI8x16)"), + ("i16x8.laneselect", "makeSIMDTernary(SIMDTernaryOp::LaneselectI16x8)"), + ("i32x4.laneselect", "makeSIMDTernary(SIMDTernaryOp::LaneselectI32x4)"), + ("i64x2.laneselect", "makeSIMDTernary(SIMDTernaryOp::LaneselectI64x2)"), + ("f32x4.relaxed_min", "makeBinary(BinaryOp::RelaxedMinVecF32x4)"), + ("f32x4.relaxed_max", "makeBinary(BinaryOp::RelaxedMaxVecF32x4)"), + ("f64x2.relaxed_min", "makeBinary(BinaryOp::RelaxedMinVecF64x2)"), + ("f64x2.relaxed_max", "makeBinary(BinaryOp::RelaxedMaxVecF64x2)"), + ("i16x8.relaxed_q15mulr_s", "makeBinary(BinaryOp::RelaxedQ15MulrSVecI16x8)"), + ("i16x8.dot_i8x16_i7x16_s", "makeBinary(BinaryOp::DotI8x16I7x16SToVecI16x8)"), + ("i32x4.dot_i8x16_i7x16_add_s", "makeSIMDTernary(SIMDTernaryOp::DotI8x16I7x16AddSToVecI32x4)"), # reference types instructions - ("ref.null", "makeRefNull(s)"), - ("ref.is_null", "makeRefIsNull(s)"), - ("ref.func", "makeRefFunc(s)"), - ("ref.eq", "makeRefEq(s)"), + ("ref.null", "makeRefNull()"), + ("ref.is_null", "makeRefIsNull()"), + ("ref.func", "makeRefFunc()"), + ("ref.eq", "makeRefEq()"), # table instructions - ("table.get", "makeTableGet(s)"), - ("table.set", "makeTableSet(s)"), - ("table.size", "makeTableSize(s)"), - ("table.grow", "makeTableGrow(s)"), - ("table.fill", "makeTableFill(s)"), - ("table.copy", "makeTableCopy(s)"), + ("table.get", "makeTableGet()"), + ("table.set", "makeTableSet()"), + ("table.size", "makeTableSize()"), + ("table.grow", "makeTableGrow()"), + ("table.fill", "makeTableFill()"), + ("table.copy", "makeTableCopy()"), # TODO: # table.init # # exception handling instructions - ("try", "makeTry(s)"), - ("try_table", "makeTryTable(s)"), - ("throw", "makeThrow(s)"), - ("rethrow", "makeRethrow(s)"), - ("throw_ref", "makeThrowRef(s)"), + ("try", "makeTry()"), + ("try_table", "makeTryTable()"), + ("throw", "makeThrow()"), + ("rethrow", "makeRethrow()"), + ("throw_ref", "makeThrowRef()"), # Multivalue pseudoinstructions - ("tuple.make", "makeTupleMake(s)"), - ("tuple.extract", "makeTupleExtract(s)"), - ("tuple.drop", "makeTupleDrop(s)"), - ("pop", "makePop(s)"), + ("tuple.make", "makeTupleMake()"), + ("tuple.extract", "makeTupleExtract()"), + ("tuple.drop", "makeTupleDrop()"), + ("pop", "makePop()"), # Typed function references instructions - ("call_ref", "makeCallRef(s, /*isReturn=*/false)"), - ("return_call_ref", "makeCallRef(s, /*isReturn=*/true)"), + ("call_ref", "makeCallRef(/*isReturn=*/false)"), + ("return_call_ref", "makeCallRef(/*isReturn=*/true)"), # Typed continuations instructions - ("cont.new", "makeContNew(s)"), - ("cont.bind", "makeContBind(s)"), - ("resume", "makeResume(s)"), - ("suspend", "makeSuspend(s)"), + ("cont.new", "makeContNew()"), + ("cont.bind", "makeContBind()"), + ("resume", "makeResume()"), + ("suspend", "makeSuspend()"), # GC - ("i31.new", "makeRefI31(s)"), # deprecated - ("ref.i31", "makeRefI31(s)"), - ("i31.get_s", "makeI31Get(s, true)"), - ("i31.get_u", "makeI31Get(s, false)"), - ("ref.test", "makeRefTest(s)"), - ("ref.cast", "makeRefCast(s)"), - ("br_on_null", "makeBrOnNull(s)"), - ("br_on_non_null", "makeBrOnNull(s, true)"), - ("br_on_cast", "makeBrOnCast(s)"), - ("br_on_cast_fail", "makeBrOnCast(s, true)"), - ("struct.new", "makeStructNew(s, false)"), - ("struct.new_default", "makeStructNew(s, true)"), - ("struct.get", "makeStructGet(s)"), - ("struct.get_s", "makeStructGet(s, true)"), - ("struct.get_u", "makeStructGet(s, false)"), - ("struct.set", "makeStructSet(s)"), - ("array.new", "makeArrayNew(s, false)"), - ("array.new_default", "makeArrayNew(s, true)"), - ("array.new_data", "makeArrayNewData(s)"), - ("array.new_elem", "makeArrayNewElem(s)"), - ("array.new_fixed", "makeArrayNewFixed(s)"), - ("array.get", "makeArrayGet(s)"), - ("array.get_s", "makeArrayGet(s, true)"), - ("array.get_u", "makeArrayGet(s, false)"), - ("array.set", "makeArraySet(s)"), - ("array.len", "makeArrayLen(s)"), - ("array.copy", "makeArrayCopy(s)"), - ("array.fill", "makeArrayFill(s)"), - ("array.init_data", "makeArrayInitData(s)"), - ("array.init_elem", "makeArrayInitElem(s)"), - ("ref.as_non_null", "makeRefAs(s, RefAsNonNull)"), - ("extern.internalize", "makeRefAs(s, ExternInternalize)"), - ("extern.externalize", "makeRefAs(s, ExternExternalize)"), - ("string.new_lossy_utf8_array", "makeStringNew(s, StringNewLossyUTF8Array)"), - ("string.new_wtf16_array", "makeStringNew(s, StringNewWTF16Array)"), - ("string.from_code_point", "makeStringNew(s, StringNewFromCodePoint)"), - ("string.const", "makeStringConst(s)"), - ("string.measure_utf8", "makeStringMeasure(s, StringMeasureUTF8)"), - ("string.measure_wtf16", "makeStringMeasure(s, StringMeasureWTF16)"), - ("stringview_wtf16.length", "makeStringMeasure(s, StringMeasureWTF16)"), - ("string.encode_lossy_utf8_array", "makeStringEncode(s, StringEncodeLossyUTF8Array)"), - ("string.encode_wtf16_array", "makeStringEncode(s, StringEncodeWTF16Array)"), - ("string.concat", "makeStringConcat(s)"), - ("string.eq", "makeStringEq(s, StringEqEqual)"), - ("string.compare", "makeStringEq(s, StringEqCompare)"), - ("stringview_wtf16.get_codeunit", "makeStringWTF16Get(s)"), - ("stringview_wtf16.slice", "makeStringSliceWTF(s)"), + ("i31.new", "makeRefI31()"), # deprecated + ("ref.i31", "makeRefI31()"), + ("i31.get_s", "makeI31Get(true)"), + ("i31.get_u", "makeI31Get(false)"), + ("ref.test", "makeRefTest()"), + ("ref.cast", "makeRefCast()"), + ("br_on_null", "makeBrOnNull()"), + ("br_on_non_null", "makeBrOnNull(true)"), + ("br_on_cast", "makeBrOnCast()"), + ("br_on_cast_fail", "makeBrOnCast(true)"), + ("struct.new", "makeStructNew(false)"), + ("struct.new_default", "makeStructNew(true)"), + ("struct.get", "makeStructGet()"), + ("struct.get_s", "makeStructGet(true)"), + ("struct.get_u", "makeStructGet(false)"), + ("struct.set", "makeStructSet()"), + ("array.new", "makeArrayNew(false)"), + ("array.new_default", "makeArrayNew(true)"), + ("array.new_data", "makeArrayNewData()"), + ("array.new_elem", "makeArrayNewElem()"), + ("array.new_fixed", "makeArrayNewFixed()"), + ("array.get", "makeArrayGet()"), + ("array.get_s", "makeArrayGet(true)"), + ("array.get_u", "makeArrayGet(false)"), + ("array.set", "makeArraySet()"), + ("array.len", "makeArrayLen()"), + ("array.copy", "makeArrayCopy()"), + ("array.fill", "makeArrayFill()"), + ("array.init_data", "makeArrayInitData()"), + ("array.init_elem", "makeArrayInitElem()"), + ("ref.as_non_null", "makeRefAs(RefAsNonNull)"), + ("extern.internalize", "makeRefAs(ExternInternalize)"), + ("extern.externalize", "makeRefAs(ExternExternalize)"), + ("string.new_lossy_utf8_array", "makeStringNew(StringNewLossyUTF8Array)"), + ("string.new_wtf16_array", "makeStringNew(StringNewWTF16Array)"), + ("string.from_code_point", "makeStringNew(StringNewFromCodePoint)"), + ("string.const", "makeStringConst()"), + ("string.measure_utf8", "makeStringMeasure(StringMeasureUTF8)"), + ("string.measure_wtf16", "makeStringMeasure(StringMeasureWTF16)"), + ("stringview_wtf16.length", "makeStringMeasure(StringMeasureWTF16)"), + ("string.encode_lossy_utf8_array", "makeStringEncode(StringEncodeLossyUTF8Array)"), + ("string.encode_wtf16_array", "makeStringEncode(StringEncodeWTF16Array)"), + ("string.concat", "makeStringConcat()"), + ("string.eq", "makeStringEq(StringEqEqual)"), + ("string.compare", "makeStringEq(StringEqCompare)"), + ("stringview_wtf16.get_codeunit", "makeStringWTF16Get()"), + ("stringview_wtf16.slice", "makeStringSliceWTF()"), # Ignored in input - ("string.as_wtf16", "ignore(s)"), + ("string.as_wtf16", "ignore()"), ] @@ -690,14 +690,14 @@ def insert(self, inst, expr): self.do_insert(inst, inst, expr) -def instruction_parser(new_parser=False): +def instruction_parser(): """Build a trie out of all the instructions, then emit it as C++ code.""" global instructions trie = Node() inst_length = 0 for inst, expr in instructions: - if new_parser and inst in {"block", "loop", "if", "try", "then", - "else", "try_table"}: + if inst in {"block", "loop", "if", "try", "then", + "else", "try_table"}: # These are either control flow handled manually or not real # instructions. Skip them. continue @@ -706,27 +706,20 @@ def instruction_parser(new_parser=False): printer = CodePrinter() - if new_parser: - printer.print_line("auto op = *keyword;") - else: - printer.print_line("using namespace std::string_view_literals;") - printer.print_line("auto op = s[0]->str().str;") - + printer.print_line("auto op = *keyword;") printer.print_line("char buf[{}] = {{}};".format(inst_length + 1)) printer.print_line("memcpy(buf, op.data(), op.size());") def print_leaf(expr, inst): - if new_parser: + if "()" in expr: expr = expr.replace("()", "(ctx, pos, annotations)") - expr = expr.replace("(s", "(ctx, pos, annotations") - printer.print_line("if (op == \"{inst}\"sv) {{".format(inst=inst)) - with printer.indent(): - printer.print_line("CHECK_ERR({expr});".format(expr=expr)) - printer.print_line("return Ok{};") - printer.print_line("}") else: - printer.print_line("if (op == \"{inst}\"sv) {{ return {expr}; }}" - .format(inst=inst, expr=expr)) + expr = expr.replace("(", "(ctx, pos, annotations, ") + printer.print_line("if (op == \"{inst}\"sv) {{".format(inst=inst)) + with printer.indent(): + printer.print_line("CHECK_ERR({expr});".format(expr=expr)) + printer.print_line("return Ok{};") + printer.print_line("}") printer.print_line("goto parse_error;") def emit(node, idx=0): @@ -755,10 +748,7 @@ def emit(node, idx=0): emit(trie) printer.print_line("parse_error:") with printer.indent(): - if new_parser: - printer.print_line("return ctx.in.err(pos, \"unrecognized instruction\");") - else: - printer.print_line("throw ParseException(std::string(op), s.line, s.col);") + printer.print_line("return ctx.in.err(pos, \"unrecognized instruction\");") def print_header(): @@ -770,22 +760,13 @@ def print_footer(): print("\n// clang-format on") -def generate_with_guard(generator, guard): - print("#ifdef {}".format(guard)) - print("#undef {}".format(guard)) - generator() - print("#endif // {}".format(guard)) - - def main(): if sys.version_info.major != 3: import datetime print("It's " + str(datetime.datetime.now().year) + "! Use Python 3!") sys.exit(1) print_header() - generate_with_guard(instruction_parser, "INSTRUCTION_PARSER") - print() - generate_with_guard(lambda: instruction_parser(True), "NEW_INSTRUCTION_PARSER") + instruction_parser() print_footer() diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index f60e5ec5960..4e7fb0b61d7 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -31,7 +31,6 @@ #include "wasm-binary.h" #include "wasm-builder.h" #include "wasm-interpreter.h" -#include "wasm-s-parser.h" #include "wasm-stack.h" #include "wasm-validator.h" #include "wasm.h" diff --git a/src/emscripten-optimizer/parser.cpp b/src/emscripten-optimizer/parser.cpp index 533043232fe..c5ecfd177ad 100644 --- a/src/emscripten-optimizer/parser.cpp +++ b/src/emscripten-optimizer/parser.cpp @@ -112,10 +112,6 @@ IString STORE("store"); IString GETTER("get"); IString SETTER("set"); -IStringSet - keywords("var const function if else do while for break continue return " - "switch case default throw try catch finally true false null new"); - const char *OPERATOR_INITS = "+-*/%<>&^|~=!,?:.", *SEPARATORS = "([;{}"; int MAX_OPERATOR_SIZE = 3; diff --git a/src/emscripten-optimizer/parser.h b/src/emscripten-optimizer/parser.h index f1d47286343..cc5032fea3f 100644 --- a/src/emscripten-optimizer/parser.h +++ b/src/emscripten-optimizer/parser.h @@ -162,8 +162,6 @@ extern IString STORE; extern IString GETTER; extern IString SETTER; -extern IStringSet keywords; - extern const char *OPERATOR_INITS, *SEPARATORS; extern int MAX_OPERATOR_SIZE, LOWEST_PREC; @@ -186,988 +184,6 @@ extern std::vector operatorClasses; extern bool isIdentInit(char x); extern bool isIdentPart(char x); -// parser - -template class Parser { - - static bool isSpace(char x) { - return x == 32 || x == 9 || x == 10 || x == 13; - } /* space, tab, linefeed/newline, or return */ - static void skipSpace(char*& curr) { - while (*curr) { - if (isSpace(*curr)) { - curr++; - continue; - } - if (curr[0] == '/' && curr[1] == '/') { - curr += 2; - while (*curr && *curr != '\n') { - curr++; - } - if (*curr) { - curr++; - } - continue; - } - if (curr[0] == '/' && curr[1] == '*') { - curr += 2; - while (*curr && (curr[0] != '*' || curr[1] != '/')) { - curr++; - } - curr += 2; - continue; - } - return; - } - } - - static bool isDigit(char x) { return x >= '0' && x <= '9'; } - - static bool hasChar(const char* list, char x) { - while (*list) { - if (*list++ == x) { - return true; - } - } - return false; - } - - // An atomic fragment of something. Stops at a natural boundary. - enum FragType { - KEYWORD = 0, - OPERATOR = 1, - IDENT = 2, - STRING = 3, // without quotes - INT = 4, - DOUBLE = 5, - SEPARATOR = 6 - }; - - struct Frag { - // MSVC does not allow unrestricted unions: - // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf -#ifndef _MSC_VER - union { -#endif - IString str; - double num; -#ifndef _MSC_VER - }; -#endif - int size; - FragType type; - - bool isNumber() const { return type == INT || type == DOUBLE; } - - explicit Frag(char* src) { - char* start = src; - if (isIdentInit(*src)) { - // read an identifier or a keyword - src++; - while (isIdentPart(*src)) { - src++; - } - if (*src == 0) { - str = IString(start); - } else { - char temp = *src; - *src = 0; - str = IString(start, false); - *src = temp; - } - type = keywords.has(str) ? KEYWORD : IDENT; - } else if (isDigit(*src) || (src[0] == '.' && isDigit(src[1]))) { - if (src[0] == '0' && (src[1] == 'x' || src[1] == 'X')) { - // Explicitly parse hex numbers of form "0x...", because strtod - // supports hex number strings only in C++11, and Visual Studio 2013 - // does not yet support that functionality. - src += 2; - num = 0; - while (1) { - if (*src >= '0' && *src <= '9') { - num *= 16; - num += *src - '0'; - } else if (*src >= 'a' && *src <= 'f') { - num *= 16; - num += *src - 'a' + 10; - } else if (*src >= 'A' && *src <= 'F') { - num *= 16; - num += *src - 'A' + 10; - } else { - break; - } - src++; - } - } else { - num = strtod(start, &src); - } - // asm.js must have a '.' for double values. however, we also tolerate - // uglify's tendency to emit without a '.' (and fix it later with a +). - // for valid asm.js input, the '.' should be enough, and for uglify - // in the emscripten optimizer pipeline, we use simple_ast where - // INT/DOUBLE is quite the same at this point anyhow - type = (std::find(start, src, '.') == src && - (wasm::isSInteger32(num) || wasm::isUInteger32(num))) - ? INT - : DOUBLE; - assert(src > start); - } else if (hasChar(OPERATOR_INITS, *src)) { - switch (*src) { - case '!': - str = src[1] == '=' ? NE : L_NOT; - break; - case '%': - str = MOD; - break; - case '&': - str = AND; - break; - case '*': - str = MUL; - break; - case '+': - str = PLUS; - break; - case ',': - str = COMMA; - break; - case '-': - str = MINUS; - break; - case '.': - str = PERIOD; - break; - case '/': - str = DIV; - break; - case ':': - str = COLON; - break; - case '<': - str = src[1] == '<' ? LSHIFT : (src[1] == '=' ? LE : LT); - break; - case '=': - str = src[1] == '=' ? EQ : SET; - break; - case '>': - str = src[1] == '>' ? (src[2] == '>' ? TRSHIFT : RSHIFT) - : (src[1] == '=' ? GE : GT); - break; - case '?': - str = QUESTION; - break; - case '^': - str = XOR; - break; - case '|': - str = OR; - break; - case '~': - str = B_NOT; - break; - default: - abort(); - } - size = str.size(); -#ifndef NDEBUG - char temp = start[size]; - start[size] = 0; - assert(str.str == start); - start[size] = temp; -#endif - type = OPERATOR; - return; - } else if (hasChar(SEPARATORS, *src)) { - type = SEPARATOR; - char temp = src[1]; - src[1] = 0; - str = IString(src, false); - src[1] = temp; - src++; - } else if (*src == '"' || *src == '\'') { - char* end = strchr(src + 1, *src); - *end = 0; - str = IString(src + 1); - src = end + 1; - type = STRING; - } else { - dump("frag parsing", src); - abort(); - } - size = src - start; - } - }; - - struct ExpressionElement { - bool isNode; - // MSVC does not allow unrestricted unions: - // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf -#ifndef _MSC_VER - union { -#endif - NodeRef node; - IString op; -#ifndef _MSC_VER - }; -#endif - ExpressionElement(NodeRef n) : isNode(true), node(n) {} - ExpressionElement(IString o) : isNode(false), op(o) {} - - NodeRef getNode() { - assert(isNode); - return node; - } - IString getOp() { - assert(!isNode); - return op; - } - }; - - // This is a list of the current stack of node-operator-node-operator-etc. - // this works by each parseExpression call appending to the vector; then - // recursing out, and the toplevel sorts it all - using ExpressionParts = std::vector; - std::vector expressionPartsStack; - - // Parses an element in a list of such elements, e.g. list of statements in a - // block, or list of parameters in a call - NodeRef parseElement(char*& src, const char* seps = ";") { - // dump("parseElement", src); - skipSpace(src); - Frag frag(src); - src += frag.size; - switch (frag.type) { - case KEYWORD: { - return parseAfterKeyword(frag, src, seps); - } - case IDENT: { - return parseAfterIdent(frag, src, seps); - } - case STRING: - case INT: - case DOUBLE: { - return parseExpression(parseFrag(frag), src, seps); - } - case SEPARATOR: { - if (frag.str == OPEN_PAREN) { - return parseExpression(parseAfterParen(src), src, seps); - } - if (frag.str == OPEN_BRACE) { - return parseExpression(parseAfterBrace(src), src, seps); - } - if (frag.str == OPEN_CURLY) { - return parseExpression(parseAfterCurly(src), src, seps); - } - abort(); - } - case OPERATOR: { - return parseExpression(frag.str, src, seps); - } - default: - /* dump("parseElement", src); printf("bad frag type: %d\n",frag.type); - */ - abort(); - } - return nullptr; - } - - NodeRef parseFrag(Frag& frag) { - switch (frag.type) { - case IDENT: - return Builder::makeName(frag.str); - case STRING: - return Builder::makeString(frag.str); - case INT: - return Builder::makeInt(uint32_t(frag.num)); - case DOUBLE: - return Builder::makeDouble(frag.num); - default: - abort(); - } - return nullptr; - } - - NodeRef parseAfterKeyword(Frag& frag, char*& src, const char* seps) { - skipSpace(src); - if (frag.str == FUNCTION) { - return parseFunction(src, seps); - } else if (frag.str == VAR) { - return parseVar(src, seps, false); - } else if (frag.str == CONST) { - return parseVar(src, seps, true); - } else if (frag.str == RETURN) { - return parseReturn(src, seps); - } else if (frag.str == IF) { - return parseIf(src, seps); - } else if (frag.str == DO) { - return parseDo(src, seps); - } else if (frag.str == WHILE) { - return parseWhile(src, seps); - } else if (frag.str == BREAK) { - return parseBreak(src, seps); - } else if (frag.str == CONTINUE) { - return parseContinue(src, seps); - } else if (frag.str == SWITCH) { - return parseSwitch(src, seps); - } else if (frag.str == NEW) { - return parseNew(src, seps); - } else if (frag.str == FOR) { - return parseFor(src, seps); - } - dump(frag.str.str, src); - abort(); - return nullptr; - } - - NodeRef parseFunction(char*& src, const char* seps) { - Frag name(src); - if (name.type == IDENT) { - src += name.size; - } else { - assert(name.type == SEPARATOR && name.str[0] == '('); - name.str = IString(); - } - NodeRef ret = Builder::makeFunction(name.str); - skipSpace(src); - assert(*src == '('); - src++; - while (1) { - skipSpace(src); - if (*src == ')') { - break; - } - Frag arg(src); - assert(arg.type == IDENT); - src += arg.size; - Builder::appendArgumentToFunction(ret, arg.str); - skipSpace(src); - if (*src == ')') { - break; - } - if (*src == ',') { - src++; - continue; - } - abort(); - } - src++; - Builder::setBlockContent(ret, parseBracketedBlock(src)); - // TODO: parse expression? - return ret; - } - - NodeRef parseVar(char*& src, const char* seps, bool is_const) { - NodeRef ret = Builder::makeVar(is_const); - while (1) { - skipSpace(src); - if (*src == ';') { - break; - } - Frag name(src); - assert(name.type == IDENT); - NodeRef value; - src += name.size; - skipSpace(src); - if (*src == '=') { - src++; - skipSpace(src); - value = parseElement(src, ";,"); - } - Builder::appendToVar(ret, name.str, value); - skipSpace(src); - if (*src == ';') { - break; - } - if (*src == ',') { - src++; - continue; - } - abort(); - } - src++; - return ret; - } - - NodeRef parseReturn(char*& src, const char* seps) { - skipSpace(src); - NodeRef value = !hasChar(seps, *src) ? parseElement(src, seps) : nullptr; - skipSpace(src); - assert(hasChar(seps, *src)); - if (*src == ';') { - src++; - } - return Builder::makeReturn(value); - } - - NodeRef parseIf(char*& src, const char* seps) { - NodeRef condition = parseParenned(src); - NodeRef ifTrue = parseMaybeBracketed(src, seps); - skipSpace(src); - NodeRef ifFalse; - if (!hasChar(seps, *src)) { - Frag next(src); - if (next.type == KEYWORD && next.str == ELSE) { - src += next.size; - ifFalse = parseMaybeBracketed(src, seps); - } - } - return Builder::makeIf(condition, ifTrue, ifFalse); - } - - NodeRef parseDo(char*& src, const char* seps) { - NodeRef body = parseMaybeBracketed(src, seps); - skipSpace(src); - Frag next(src); - assert(next.type == KEYWORD && next.str == WHILE); - src += next.size; - NodeRef condition = parseParenned(src); - return Builder::makeDo(body, condition); - } - - NodeRef parseWhile(char*& src, const char* seps) { - NodeRef condition = parseParenned(src); - NodeRef body = parseMaybeBracketed(src, seps); - return Builder::makeWhile(condition, body); - } - - NodeRef parseFor(char*& src, const char* seps) { - skipSpace(src); - assert(*src == '('); - src++; - NodeRef init = parseElement(src, ";"); - skipSpace(src); - assert(*src == ';'); - src++; - NodeRef condition = parseElement(src, ";"); - skipSpace(src); - assert(*src == ';'); - src++; - NodeRef inc = parseElement(src, ")"); - skipSpace(src); - assert(*src == ')'); - src++; - NodeRef body = parseMaybeBracketed(src, seps); - return Builder::makeFor(init, condition, inc, body); - } - - NodeRef parseBreak(char*& src, const char* seps) { - skipSpace(src); - Frag next(src); - if (next.type == IDENT) { - src += next.size; - } - return Builder::makeBreak(next.type == IDENT ? next.str : IString()); - } - - NodeRef parseContinue(char*& src, const char* seps) { - skipSpace(src); - Frag next(src); - if (next.type == IDENT) { - src += next.size; - } - return Builder::makeContinue(next.type == IDENT ? next.str : IString()); - } - - NodeRef parseSwitch(char*& src, const char* seps) { - NodeRef ret = Builder::makeSwitch(parseParenned(src)); - skipSpace(src); - assert(*src == '{'); - src++; - while (1) { - // find all cases and possibly a default - skipSpace(src); - if (*src == '}') { - break; - } - Frag next(src); - if (next.type == KEYWORD) { - if (next.str == CASE) { - src += next.size; - skipSpace(src); - NodeRef arg; - Frag value(src); - if (value.isNumber()) { - arg = parseFrag(value); - src += value.size; - } else if (value.type == OPERATOR) { - // negative number - assert(value.str == MINUS); - src += value.size; - skipSpace(src); - Frag value2(src); - assert(value2.isNumber()); - arg = Builder::makePrefix(MINUS, parseFrag(value2)); - src += value2.size; - } else { - // identifier and function call - assert(value.type == IDENT); - src += value.size; - skipSpace(src); - arg = parseCall(parseFrag(value), src); - } - Builder::appendCaseToSwitch(ret, arg); - skipSpace(src); - assert(*src == ':'); - src++; - continue; - } else if (next.str == DEFAULT) { - src += next.size; - Builder::appendDefaultToSwitch(ret); - skipSpace(src); - assert(*src == ':'); - src++; - continue; - } - // otherwise, may be some keyword that happens to start a block (e.g. - // case 1: _return_ 5) - } - // not case X: or default: or }, so must be some code - skipSpace(src); - bool explicitBlock = *src == '{'; - NodeRef subBlock = explicitBlock ? parseBracketedBlock(src) - : parseBlock(src, ";}", CASE, DEFAULT); - Builder::appendCodeToSwitch(ret, subBlock, explicitBlock); - } - skipSpace(src); - assert(*src == '}'); - src++; - return ret; - } - - NodeRef parseNew(char*& src, const char* seps) { - return Builder::makeNew(parseElement(src, seps)); - } - - NodeRef parseAfterIdent(Frag& frag, char*& src, const char* seps) { - skipSpace(src); - if (*src == '(') { - return parseExpression(parseCall(parseFrag(frag), src), src, seps); - } - if (*src == '[') { - return parseExpression(parseIndexing(parseFrag(frag), src), src, seps); - } - if (*src == ':' && expressionPartsStack.back().size() == 0) { - src++; - skipSpace(src); - NodeRef inner; - if (*src == '{') { - // context lets us know this is not an object, but a block - inner = parseBracketedBlock(src); - } else { - inner = parseElement(src, seps); - } - return Builder::makeLabel(frag.str, inner); - } - if (*src == '.') { - return parseExpression(parseDotting(parseFrag(frag), src), src, seps); - } - return parseExpression(parseFrag(frag), src, seps); - } - - NodeRef parseCall(NodeRef target, char*& src) { - expressionPartsStack.resize(expressionPartsStack.size() + 1); - assert(*src == '('); - src++; - NodeRef ret = Builder::makeCall(target); - while (1) { - skipSpace(src); - if (*src == ')') { - break; - } - Builder::appendToCall(ret, parseElement(src, ",)")); - skipSpace(src); - if (*src == ')') { - break; - } - if (*src == ',') { - src++; - continue; - } - abort(); - } - src++; - assert(expressionPartsStack.back().size() == 0); - expressionPartsStack.pop_back(); - return ret; - } - - NodeRef parseIndexing(NodeRef target, char*& src) { - expressionPartsStack.resize(expressionPartsStack.size() + 1); - assert(*src == '['); - src++; - NodeRef ret = Builder::makeIndexing(target, parseElement(src, "]")); - skipSpace(src); - assert(*src == ']'); - src++; - assert(expressionPartsStack.back().size() == 0); - expressionPartsStack.pop_back(); - return ret; - } - - NodeRef parseDotting(NodeRef target, char*& src) { - assert(*src == '.'); - src++; - Frag key(src); - assert(key.type == IDENT); - src += key.size; - return Builder::makeDot(target, key.str); - } - - NodeRef parseAfterParen(char*& src) { - expressionPartsStack.resize(expressionPartsStack.size() + 1); - skipSpace(src); - NodeRef ret = parseElement(src, ")"); - skipSpace(src); - assert(*src == ')'); - src++; - assert(expressionPartsStack.back().size() == 0); - expressionPartsStack.pop_back(); - return ret; - } - - NodeRef parseAfterBrace(char*& src) { - expressionPartsStack.resize(expressionPartsStack.size() + 1); - NodeRef ret = Builder::makeArray(); - while (1) { - skipSpace(src); - assert(*src); - if (*src == ']') { - break; - } - NodeRef element = parseElement(src, ",]"); - Builder::appendToArray(ret, element); - skipSpace(src); - if (*src == ']') { - break; - } - if (*src == ',') { - src++; - continue; - } - abort(); - } - src++; - return ret; - } - - NodeRef parseAfterCurly(char*& src) { - expressionPartsStack.resize(expressionPartsStack.size() + 1); - NodeRef ret = Builder::makeObject(); - while (1) { - skipSpace(src); - assert(*src); - if (*src == '}') { - break; - } - Frag key(src); - assert(key.type == IDENT || key.type == STRING); - src += key.size; - skipSpace(src); - assert(*src == ':'); - src++; - NodeRef value = parseElement(src, ",}"); - Builder::appendToObject(ret, key.str, value); - skipSpace(src); - if (*src == '}') { - break; - } - if (*src == ',') { - src++; - continue; - } - abort(); - } - src++; - return ret; - } - - void dumpParts(ExpressionParts& parts, int i) { - printf("expressionparts: %d (at %d)\n", parts.size(), i); - printf("| "); - for (int i = 0; i < parts.size(); i++) { - if (parts[i].isNode) { - parts[i].getNode()->stringify(std::cout); - printf(" "); - } else { - printf(" _%s_ ", parts[i].getOp().str); - } - } - printf("|\n"); - } - - NodeRef makeBinary(NodeRef left, IString op, NodeRef right) { - if (op == PERIOD) { - return Builder::makeDot(left, right); - } else { - return Builder::makeBinary(left, op, right); - } - } - - NodeRef - parseExpression(ExpressionElement initial, char*& src, const char* seps) { - // dump("parseExpression", src); - ExpressionParts& parts = expressionPartsStack.back(); - skipSpace(src); - if (*src == 0 || hasChar(seps, *src)) { - if (parts.size() > 0) { - parts.push_back(initial); // cherry on top of the cake - } - return initial.getNode(); - } - bool top = parts.size() == 0; - if (initial.isNode) { - Frag next(src); - if (next.type == OPERATOR) { - parts.push_back(initial); - src += next.size; - parts.push_back(next.str); - } else { - if (*src == '(') { - initial = parseCall(initial.getNode(), src); - } else if (*src == '[') { - initial = parseIndexing(initial.getNode(), src); - } else { - dump("bad parseExpression state", src); - abort(); - } - return parseExpression(initial, src, seps); - } - } else { - parts.push_back(initial); - } - NodeRef last = parseElement(src, seps); - if (!top) { - return last; - } - { - // |parts| may have been invalidated by that call - ExpressionParts& parts = expressionPartsStack.back(); - // we are the toplevel. sort it all out - // collapse right to left, highest priority first - // dumpParts(parts, 0); - for (auto& ops : operatorClasses) { - if (ops.rtl) { - // right to left - for (int i = parts.size() - 1; i >= 0; i--) { - if (parts[i].isNode) { - continue; - } - IString op = parts[i].getOp(); - if (!ops.ops.has(op)) { - continue; - } - if (ops.type == OperatorClass::Binary && i > 0 && - i < (int)parts.size() - 1) { - parts[i] = - makeBinary(parts[i - 1].getNode(), op, parts[i + 1].getNode()); - parts.erase(parts.begin() + i + 1); - parts.erase(parts.begin() + i - 1); - } else if (ops.type == OperatorClass::Prefix && - i < (int)parts.size() - 1) { - if (i > 0 && parts[i - 1].isNode) { - // cannot apply prefix operator if it would join two nodes - continue; - } - parts[i] = Builder::makePrefix(op, parts[i + 1].getNode()); - parts.erase(parts.begin() + i + 1); - } else if (ops.type == OperatorClass::Tertiary) { - // we must be at X ? Y : Z - // ^ - // dumpParts(parts, i); - if (op != COLON) { - continue; - } - assert(i < (int)parts.size() - 1 && i >= 3); - if (parts[i - 2].getOp() != QUESTION) { - continue; // e.g. x ? y ? 1 : 0 : 2 - } - parts[i - 3] = Builder::makeConditional(parts[i - 3].getNode(), - parts[i - 1].getNode(), - parts[i + 1].getNode()); - parts.erase(parts.begin() + i - 2, parts.begin() + i + 2); - // basically a reset, due to things like x ? y ? 1 : 0 : 2 - i = parts.size(); - } // TODO: postfix - } - } else { - // left to right - for (int i = 0; i < (int)parts.size(); i++) { - if (parts[i].isNode) { - continue; - } - IString op = parts[i].getOp(); - if (!ops.ops.has(op)) { - continue; - } - if (ops.type == OperatorClass::Binary && i > 0 && - i < (int)parts.size() - 1) { - parts[i] = - makeBinary(parts[i - 1].getNode(), op, parts[i + 1].getNode()); - parts.erase(parts.begin() + i + 1); - parts.erase(parts.begin() + i - 1); - i--; - } else if (ops.type == OperatorClass::Prefix && - i < (int)parts.size() - 1) { - if (i > 0 && parts[i - 1].isNode) { - // cannot apply prefix operator if it would join two nodes - continue; - } - parts[i] = Builder::makePrefix(op, parts[i + 1].getNode()); - parts.erase(parts.begin() + i + 1); - // allow a previous prefix operator to cascade - i = std::max(i - 2, 0); - } // TODO: tertiary, postfix - } - } - } - assert(parts.size() == 1); - NodeRef ret = parts[0].getNode(); - parts.clear(); - return ret; - } - } - - // Parses a block of code (e.g. a bunch of statements inside {,}, or the top - // level of o file) - NodeRef parseBlock(char*& src, - const char* seps = ";", - IString keywordSep1 = IString(), - IString keywordSep2 = IString()) { - NodeRef block = Builder::makeBlock(); - // dump("parseBlock", src); - while (1) { - skipSpace(src); - if (*src == 0) { - break; - } - if (*src == ';') { - src++; // skip a statement in this block - continue; - } - if (hasChar(seps, *src)) { - break; - } - if (!!keywordSep1) { - Frag next(src); - if (next.type == KEYWORD && next.str == keywordSep1) { - break; - } - } - if (!!keywordSep2) { - Frag next(src); - if (next.type == KEYWORD && next.str == keywordSep2) { - break; - } - } - NodeRef element = parseElementOrStatement(src, seps); - Builder::appendToBlock(block, element); - } - return block; - } - - NodeRef parseBracketedBlock(char*& src) { - skipSpace(src); - assert(*src == '{'); - src++; - // the two are not symmetrical, ; is just internally separating, } is the - // final one - parseBlock knows all this - NodeRef block = parseBlock(src, ";}"); - assert(*src == '}'); - src++; - return block; - } - - NodeRef parseElementOrStatement(char*& src, const char* seps) { - skipSpace(src); - if (*src == ';') { - src++; - // we don't need the brackets here, but oh well - return Builder::makeBlock(); - } - if (*src == '{') { // detect a trivial {} in a statement context - char* before = src; - src++; - skipSpace(src); - if (*src == '}') { - src++; - // we don't need the brackets here, but oh well - return Builder::makeBlock(); - } - src = before; - } - NodeRef ret = parseElement(src, seps); - skipSpace(src); - if (*src == ';') { - ret = Builder::makeStatement(ret); - src++; - } - return ret; - } - - NodeRef parseMaybeBracketed(char*& src, const char* seps) { - skipSpace(src); - return *src == '{' ? parseBracketedBlock(src) - : parseElementOrStatement(src, seps); - } - - NodeRef parseParenned(char*& src) { - skipSpace(src); - assert(*src == '('); - src++; - NodeRef ret = parseElement(src, ")"); - skipSpace(src); - assert(*src == ')'); - src++; - return ret; - } - - // Debugging - - char* allSource = nullptr; - int allSize = 0; - - static void dump(const char* where, char* curr) { - /* - printf("%s:\n=============\n", where); - for (int i = 0; i < allSize; i++) - printf("%c", allSource[i] ? allSource[i] : - '?'); - printf("\n"); - for (int i = 0; i < (curr - allSource); i++) printf(" "); - printf("^\n=============\n"); - */ - fprintf(stderr, "%s:\n==========\n", where); - int newlinesLeft = 2; - int charsLeft = 200; - while (*curr) { - if (*curr == '\n') { - newlinesLeft--; - if (newlinesLeft == 0) { - break; - } - } - charsLeft--; - if (charsLeft == 0) { - break; - } - fprintf(stderr, "%c", *curr++); - } - fprintf(stderr, "\n\n"); - } - -public: - Parser() { expressionPartsStack.resize(1); } - - // Highest-level parsing, as of a JavaScript script file. - NodeRef parseToplevel(char* src) { - allSource = src; - allSize = strlen(src); - NodeRef toplevel = Builder::makeToplevel(); - Builder::setBlockContent(toplevel, parseBlock(src)); - return toplevel; - } -}; - } // namespace cashew #endif // wasm_parser_h diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index a451805dbd8..5cdb29d833d 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -2,3467 +2,6 @@ // clang-format off -#ifdef INSTRUCTION_PARSER -#undef INSTRUCTION_PARSER -using namespace std::string_view_literals; -auto op = s[0]->str().str; -char buf[33] = {}; -memcpy(buf, op.data(), op.size()); -switch (buf[0]) { - case 'a': { - switch (buf[1]) { - case 'r': { - switch (buf[6]) { - case 'c': - if (op == "array.copy"sv) { return makeArrayCopy(s); } - goto parse_error; - case 'f': - if (op == "array.fill"sv) { return makeArrayFill(s); } - goto parse_error; - case 'g': { - switch (buf[9]) { - case '\0': - if (op == "array.get"sv) { return makeArrayGet(s); } - goto parse_error; - case '_': { - switch (buf[10]) { - case 's': - if (op == "array.get_s"sv) { return makeArrayGet(s, true); } - goto parse_error; - case 'u': - if (op == "array.get_u"sv) { return makeArrayGet(s, false); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'i': { - switch (buf[11]) { - case 'd': - if (op == "array.init_data"sv) { return makeArrayInitData(s); } - goto parse_error; - case 'e': - if (op == "array.init_elem"sv) { return makeArrayInitElem(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': - if (op == "array.len"sv) { return makeArrayLen(s); } - goto parse_error; - case 'n': { - switch (buf[9]) { - case '\0': - if (op == "array.new"sv) { return makeArrayNew(s, false); } - goto parse_error; - case '_': { - switch (buf[10]) { - case 'd': { - switch (buf[11]) { - case 'a': - if (op == "array.new_data"sv) { return makeArrayNewData(s); } - goto parse_error; - case 'e': - if (op == "array.new_default"sv) { return makeArrayNew(s, true); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': - if (op == "array.new_elem"sv) { return makeArrayNewElem(s); } - goto parse_error; - case 'f': - if (op == "array.new_fixed"sv) { return makeArrayNewFixed(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 's': - if (op == "array.set"sv) { return makeArraySet(s); } - goto parse_error; - default: goto parse_error; - } - } - case 't': - if (op == "atomic.fence"sv) { return makeAtomicFence(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'b': { - switch (buf[1]) { - case 'l': - if (op == "block"sv) { return makeBlock(s); } - goto parse_error; - case 'r': { - switch (buf[2]) { - case '\0': - if (op == "br"sv) { return makeBreak(s, false); } - goto parse_error; - case '_': { - switch (buf[3]) { - case 'i': - if (op == "br_if"sv) { return makeBreak(s, true); } - goto parse_error; - case 'o': { - switch (buf[6]) { - case 'c': { - switch (buf[10]) { - case '\0': - if (op == "br_on_cast"sv) { return makeBrOnCast(s); } - goto parse_error; - case '_': - if (op == "br_on_cast_fail"sv) { return makeBrOnCast(s, true); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': { - switch (buf[7]) { - case 'o': - if (op == "br_on_non_null"sv) { return makeBrOnNull(s, true); } - goto parse_error; - case 'u': - if (op == "br_on_null"sv) { return makeBrOnNull(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 't': - if (op == "br_table"sv) { return makeBreakTable(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'c': { - switch (buf[1]) { - case 'a': { - switch (buf[4]) { - case '\0': - if (op == "call"sv) { return makeCall(s, /*isReturn=*/false); } - goto parse_error; - case '_': { - switch (buf[5]) { - case 'i': - if (op == "call_indirect"sv) { return makeCallIndirect(s, /*isReturn=*/false); } - goto parse_error; - case 'r': - if (op == "call_ref"sv) { return makeCallRef(s, /*isReturn=*/false); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'o': { - switch (buf[5]) { - case 'b': - if (op == "cont.bind"sv) { return makeContBind(s); } - goto parse_error; - case 'n': - if (op == "cont.new"sv) { return makeContNew(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'd': { - switch (buf[1]) { - case 'a': - if (op == "data.drop"sv) { return makeDataDrop(s); } - goto parse_error; - case 'r': - if (op == "drop"sv) { return makeDrop(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[1]) { - case 'l': - if (op == "else"sv) { return makeThenOrElse(s); } - goto parse_error; - case 'x': { - switch (buf[7]) { - case 'e': - if (op == "extern.externalize"sv) { return makeRefAs(s, ExternExternalize); } - goto parse_error; - case 'i': - if (op == "extern.internalize"sv) { return makeRefAs(s, ExternInternalize); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'f': { - switch (buf[1]) { - case '3': { - switch (buf[3]) { - case '.': { - switch (buf[4]) { - case 'a': { - switch (buf[5]) { - case 'b': - if (op == "f32.abs"sv) { return makeUnary(s, UnaryOp::AbsFloat32); } - goto parse_error; - case 'd': - if (op == "f32.add"sv) { return makeBinary(s, BinaryOp::AddFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': { - switch (buf[5]) { - case 'e': - if (op == "f32.ceil"sv) { return makeUnary(s, UnaryOp::CeilFloat32); } - goto parse_error; - case 'o': { - switch (buf[6]) { - case 'n': { - switch (buf[7]) { - case 's': - if (op == "f32.const"sv) { return makeConst(s, Type::f32); } - goto parse_error; - case 'v': { - switch (buf[13]) { - case '3': { - switch (buf[16]) { - case 's': - if (op == "f32.convert_i32_s"sv) { return makeUnary(s, UnaryOp::ConvertSInt32ToFloat32); } - goto parse_error; - case 'u': - if (op == "f32.convert_i32_u"sv) { return makeUnary(s, UnaryOp::ConvertUInt32ToFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (buf[16]) { - case 's': - if (op == "f32.convert_i64_s"sv) { return makeUnary(s, UnaryOp::ConvertSInt64ToFloat32); } - goto parse_error; - case 'u': - if (op == "f32.convert_i64_u"sv) { return makeUnary(s, UnaryOp::ConvertUInt64ToFloat32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "f32.copysign"sv) { return makeBinary(s, BinaryOp::CopySignFloat32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'd': { - switch (buf[5]) { - case 'e': - if (op == "f32.demote_f64"sv) { return makeUnary(s, UnaryOp::DemoteFloat64); } - goto parse_error; - case 'i': - if (op == "f32.div"sv) { return makeBinary(s, BinaryOp::DivFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': - if (op == "f32.eq"sv) { return makeBinary(s, BinaryOp::EqFloat32); } - goto parse_error; - case 'f': - if (op == "f32.floor"sv) { return makeUnary(s, UnaryOp::FloorFloat32); } - goto parse_error; - case 'g': { - switch (buf[5]) { - case 'e': - if (op == "f32.ge"sv) { return makeBinary(s, BinaryOp::GeFloat32); } - goto parse_error; - case 't': - if (op == "f32.gt"sv) { return makeBinary(s, BinaryOp::GtFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[5]) { - case 'e': - if (op == "f32.le"sv) { return makeBinary(s, BinaryOp::LeFloat32); } - goto parse_error; - case 'o': - if (op == "f32.load"sv) { return makeLoad(s, Type::f32, /*signed=*/false, 4, /*isAtomic=*/false); } - goto parse_error; - case 't': - if (op == "f32.lt"sv) { return makeBinary(s, BinaryOp::LtFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (buf[5]) { - case 'a': - if (op == "f32.max"sv) { return makeBinary(s, BinaryOp::MaxFloat32); } - goto parse_error; - case 'i': - if (op == "f32.min"sv) { return makeBinary(s, BinaryOp::MinFloat32); } - goto parse_error; - case 'u': - if (op == "f32.mul"sv) { return makeBinary(s, BinaryOp::MulFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': { - switch (buf[6]) { - case '\0': - if (op == "f32.ne"sv) { return makeBinary(s, BinaryOp::NeFloat32); } - goto parse_error; - case 'a': - if (op == "f32.nearest"sv) { return makeUnary(s, UnaryOp::NearestFloat32); } - goto parse_error; - case 'g': - if (op == "f32.neg"sv) { return makeUnary(s, UnaryOp::NegFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': - if (op == "f32.reinterpret_i32"sv) { return makeUnary(s, UnaryOp::ReinterpretInt32); } - goto parse_error; - case 's': { - switch (buf[5]) { - case 'q': - if (op == "f32.sqrt"sv) { return makeUnary(s, UnaryOp::SqrtFloat32); } - goto parse_error; - case 't': - if (op == "f32.store"sv) { return makeStore(s, Type::f32, 4, /*isAtomic=*/false); } - goto parse_error; - case 'u': - if (op == "f32.sub"sv) { return makeBinary(s, BinaryOp::SubFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case 't': - if (op == "f32.trunc"sv) { return makeUnary(s, UnaryOp::TruncFloat32); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[6]) { - case 'a': { - switch (buf[7]) { - case 'b': - if (op == "f32x4.abs"sv) { return makeUnary(s, UnaryOp::AbsVecF32x4); } - goto parse_error; - case 'd': - if (op == "f32x4.add"sv) { return makeBinary(s, BinaryOp::AddVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': { - switch (buf[7]) { - case 'e': - if (op == "f32x4.ceil"sv) { return makeUnary(s, UnaryOp::CeilVecF32x4); } - goto parse_error; - case 'o': { - switch (buf[20]) { - case 's': - if (op == "f32x4.convert_i32x4_s"sv) { return makeUnary(s, UnaryOp::ConvertSVecI32x4ToVecF32x4); } - goto parse_error; - case 'u': - if (op == "f32x4.convert_i32x4_u"sv) { return makeUnary(s, UnaryOp::ConvertUVecI32x4ToVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'd': { - switch (buf[7]) { - case 'e': - if (op == "f32x4.demote_f64x2_zero"sv) { return makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4); } - goto parse_error; - case 'i': - if (op == "f32x4.div"sv) { return makeBinary(s, BinaryOp::DivVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[7]) { - case 'q': - if (op == "f32x4.eq"sv) { return makeBinary(s, BinaryOp::EqVecF32x4); } - goto parse_error; - case 'x': - if (op == "f32x4.extract_lane"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecF32x4, 4); } - goto parse_error; - default: goto parse_error; - } - } - case 'f': - if (op == "f32x4.floor"sv) { return makeUnary(s, UnaryOp::FloorVecF32x4); } - goto parse_error; - case 'g': { - switch (buf[7]) { - case 'e': - if (op == "f32x4.ge"sv) { return makeBinary(s, BinaryOp::GeVecF32x4); } - goto parse_error; - case 't': - if (op == "f32x4.gt"sv) { return makeBinary(s, BinaryOp::GtVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[7]) { - case 'e': - if (op == "f32x4.le"sv) { return makeBinary(s, BinaryOp::LeVecF32x4); } - goto parse_error; - case 't': - if (op == "f32x4.lt"sv) { return makeBinary(s, BinaryOp::LtVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (buf[7]) { - case 'a': - if (op == "f32x4.max"sv) { return makeBinary(s, BinaryOp::MaxVecF32x4); } - goto parse_error; - case 'i': - if (op == "f32x4.min"sv) { return makeBinary(s, BinaryOp::MinVecF32x4); } - goto parse_error; - case 'u': - if (op == "f32x4.mul"sv) { return makeBinary(s, BinaryOp::MulVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': { - switch (buf[8]) { - case '\0': - if (op == "f32x4.ne"sv) { return makeBinary(s, BinaryOp::NeVecF32x4); } - goto parse_error; - case 'a': - if (op == "f32x4.nearest"sv) { return makeUnary(s, UnaryOp::NearestVecF32x4); } - goto parse_error; - case 'g': - if (op == "f32x4.neg"sv) { return makeUnary(s, UnaryOp::NegVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'p': { - switch (buf[8]) { - case 'a': - if (op == "f32x4.pmax"sv) { return makeBinary(s, BinaryOp::PMaxVecF32x4); } - goto parse_error; - case 'i': - if (op == "f32x4.pmin"sv) { return makeBinary(s, BinaryOp::PMinVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': { - switch (buf[8]) { - case 'l': { - switch (buf[14]) { - case 'f': { - switch (buf[16]) { - case 'a': - if (op == "f32x4.relaxed_fma"sv) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF32x4); } - goto parse_error; - case 's': - if (op == "f32x4.relaxed_fms"sv) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (buf[15]) { - case 'a': - if (op == "f32x4.relaxed_max"sv) { return makeBinary(s, BinaryOp::RelaxedMaxVecF32x4); } - goto parse_error; - case 'i': - if (op == "f32x4.relaxed_min"sv) { return makeBinary(s, BinaryOp::RelaxedMinVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "f32x4.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF32x4, 4); } - goto parse_error; - default: goto parse_error; - } - } - case 's': { - switch (buf[7]) { - case 'p': - if (op == "f32x4.splat"sv) { return makeUnary(s, UnaryOp::SplatVecF32x4); } - goto parse_error; - case 'q': - if (op == "f32x4.sqrt"sv) { return makeUnary(s, UnaryOp::SqrtVecF32x4); } - goto parse_error; - case 'u': - if (op == "f32x4.sub"sv) { return makeBinary(s, BinaryOp::SubVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 't': - if (op == "f32x4.trunc"sv) { return makeUnary(s, UnaryOp::TruncVecF32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '6': { - switch (buf[3]) { - case '.': { - switch (buf[4]) { - case 'a': { - switch (buf[5]) { - case 'b': - if (op == "f64.abs"sv) { return makeUnary(s, UnaryOp::AbsFloat64); } - goto parse_error; - case 'd': - if (op == "f64.add"sv) { return makeBinary(s, BinaryOp::AddFloat64); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': { - switch (buf[5]) { - case 'e': - if (op == "f64.ceil"sv) { return makeUnary(s, UnaryOp::CeilFloat64); } - goto parse_error; - case 'o': { - switch (buf[6]) { - case 'n': { - switch (buf[7]) { - case 's': - if (op == "f64.const"sv) { return makeConst(s, Type::f64); } - goto parse_error; - case 'v': { - switch (buf[13]) { - case '3': { - switch (buf[16]) { - case 's': - if (op == "f64.convert_i32_s"sv) { return makeUnary(s, UnaryOp::ConvertSInt32ToFloat64); } - goto parse_error; - case 'u': - if (op == "f64.convert_i32_u"sv) { return makeUnary(s, UnaryOp::ConvertUInt32ToFloat64); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (buf[16]) { - case 's': - if (op == "f64.convert_i64_s"sv) { return makeUnary(s, UnaryOp::ConvertSInt64ToFloat64); } - goto parse_error; - case 'u': - if (op == "f64.convert_i64_u"sv) { return makeUnary(s, UnaryOp::ConvertUInt64ToFloat64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "f64.copysign"sv) { return makeBinary(s, BinaryOp::CopySignFloat64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'd': - if (op == "f64.div"sv) { return makeBinary(s, BinaryOp::DivFloat64); } - goto parse_error; - case 'e': - if (op == "f64.eq"sv) { return makeBinary(s, BinaryOp::EqFloat64); } - goto parse_error; - case 'f': - if (op == "f64.floor"sv) { return makeUnary(s, UnaryOp::FloorFloat64); } - goto parse_error; - case 'g': { - switch (buf[5]) { - case 'e': - if (op == "f64.ge"sv) { return makeBinary(s, BinaryOp::GeFloat64); } - goto parse_error; - case 't': - if (op == "f64.gt"sv) { return makeBinary(s, BinaryOp::GtFloat64); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[5]) { - case 'e': - if (op == "f64.le"sv) { return makeBinary(s, BinaryOp::LeFloat64); } - goto parse_error; - case 'o': - if (op == "f64.load"sv) { return makeLoad(s, Type::f64, /*signed=*/false, 8, /*isAtomic=*/false); } - goto parse_error; - case 't': - if (op == "f64.lt"sv) { return makeBinary(s, BinaryOp::LtFloat64); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (buf[5]) { - case 'a': - if (op == "f64.max"sv) { return makeBinary(s, BinaryOp::MaxFloat64); } - goto parse_error; - case 'i': - if (op == "f64.min"sv) { return makeBinary(s, BinaryOp::MinFloat64); } - goto parse_error; - case 'u': - if (op == "f64.mul"sv) { return makeBinary(s, BinaryOp::MulFloat64); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': { - switch (buf[6]) { - case '\0': - if (op == "f64.ne"sv) { return makeBinary(s, BinaryOp::NeFloat64); } - goto parse_error; - case 'a': - if (op == "f64.nearest"sv) { return makeUnary(s, UnaryOp::NearestFloat64); } - goto parse_error; - case 'g': - if (op == "f64.neg"sv) { return makeUnary(s, UnaryOp::NegFloat64); } - goto parse_error; - default: goto parse_error; - } - } - case 'p': - if (op == "f64.promote_f32"sv) { return makeUnary(s, UnaryOp::PromoteFloat32); } - goto parse_error; - case 'r': - if (op == "f64.reinterpret_i64"sv) { return makeUnary(s, UnaryOp::ReinterpretInt64); } - goto parse_error; - case 's': { - switch (buf[5]) { - case 'q': - if (op == "f64.sqrt"sv) { return makeUnary(s, UnaryOp::SqrtFloat64); } - goto parse_error; - case 't': - if (op == "f64.store"sv) { return makeStore(s, Type::f64, 8, /*isAtomic=*/false); } - goto parse_error; - case 'u': - if (op == "f64.sub"sv) { return makeBinary(s, BinaryOp::SubFloat64); } - goto parse_error; - default: goto parse_error; - } - } - case 't': - if (op == "f64.trunc"sv) { return makeUnary(s, UnaryOp::TruncFloat64); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[6]) { - case 'a': { - switch (buf[7]) { - case 'b': - if (op == "f64x2.abs"sv) { return makeUnary(s, UnaryOp::AbsVecF64x2); } - goto parse_error; - case 'd': - if (op == "f64x2.add"sv) { return makeBinary(s, BinaryOp::AddVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': { - switch (buf[7]) { - case 'e': - if (op == "f64x2.ceil"sv) { return makeUnary(s, UnaryOp::CeilVecF64x2); } - goto parse_error; - case 'o': { - switch (buf[24]) { - case 's': - if (op == "f64x2.convert_low_i32x4_s"sv) { return makeUnary(s, UnaryOp::ConvertLowSVecI32x4ToVecF64x2); } - goto parse_error; - case 'u': - if (op == "f64x2.convert_low_i32x4_u"sv) { return makeUnary(s, UnaryOp::ConvertLowUVecI32x4ToVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'd': - if (op == "f64x2.div"sv) { return makeBinary(s, BinaryOp::DivVecF64x2); } - goto parse_error; - case 'e': { - switch (buf[7]) { - case 'q': - if (op == "f64x2.eq"sv) { return makeBinary(s, BinaryOp::EqVecF64x2); } - goto parse_error; - case 'x': - if (op == "f64x2.extract_lane"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecF64x2, 2); } - goto parse_error; - default: goto parse_error; - } - } - case 'f': - if (op == "f64x2.floor"sv) { return makeUnary(s, UnaryOp::FloorVecF64x2); } - goto parse_error; - case 'g': { - switch (buf[7]) { - case 'e': - if (op == "f64x2.ge"sv) { return makeBinary(s, BinaryOp::GeVecF64x2); } - goto parse_error; - case 't': - if (op == "f64x2.gt"sv) { return makeBinary(s, BinaryOp::GtVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[7]) { - case 'e': - if (op == "f64x2.le"sv) { return makeBinary(s, BinaryOp::LeVecF64x2); } - goto parse_error; - case 't': - if (op == "f64x2.lt"sv) { return makeBinary(s, BinaryOp::LtVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (buf[7]) { - case 'a': - if (op == "f64x2.max"sv) { return makeBinary(s, BinaryOp::MaxVecF64x2); } - goto parse_error; - case 'i': - if (op == "f64x2.min"sv) { return makeBinary(s, BinaryOp::MinVecF64x2); } - goto parse_error; - case 'u': - if (op == "f64x2.mul"sv) { return makeBinary(s, BinaryOp::MulVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': { - switch (buf[8]) { - case '\0': - if (op == "f64x2.ne"sv) { return makeBinary(s, BinaryOp::NeVecF64x2); } - goto parse_error; - case 'a': - if (op == "f64x2.nearest"sv) { return makeUnary(s, UnaryOp::NearestVecF64x2); } - goto parse_error; - case 'g': - if (op == "f64x2.neg"sv) { return makeUnary(s, UnaryOp::NegVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'p': { - switch (buf[7]) { - case 'm': { - switch (buf[8]) { - case 'a': - if (op == "f64x2.pmax"sv) { return makeBinary(s, BinaryOp::PMaxVecF64x2); } - goto parse_error; - case 'i': - if (op == "f64x2.pmin"sv) { return makeBinary(s, BinaryOp::PMinVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': - if (op == "f64x2.promote_low_f32x4"sv) { return makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': { - switch (buf[8]) { - case 'l': { - switch (buf[14]) { - case 'f': { - switch (buf[16]) { - case 'a': - if (op == "f64x2.relaxed_fma"sv) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF64x2); } - goto parse_error; - case 's': - if (op == "f64x2.relaxed_fms"sv) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (buf[15]) { - case 'a': - if (op == "f64x2.relaxed_max"sv) { return makeBinary(s, BinaryOp::RelaxedMaxVecF64x2); } - goto parse_error; - case 'i': - if (op == "f64x2.relaxed_min"sv) { return makeBinary(s, BinaryOp::RelaxedMinVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "f64x2.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF64x2, 2); } - goto parse_error; - default: goto parse_error; - } - } - case 's': { - switch (buf[7]) { - case 'p': - if (op == "f64x2.splat"sv) { return makeUnary(s, UnaryOp::SplatVecF64x2); } - goto parse_error; - case 'q': - if (op == "f64x2.sqrt"sv) { return makeUnary(s, UnaryOp::SqrtVecF64x2); } - goto parse_error; - case 'u': - if (op == "f64x2.sub"sv) { return makeBinary(s, BinaryOp::SubVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 't': - if (op == "f64x2.trunc"sv) { return makeUnary(s, UnaryOp::TruncVecF64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'g': { - switch (buf[7]) { - case 'g': - if (op == "global.get"sv) { return makeGlobalGet(s); } - goto parse_error; - case 's': - if (op == "global.set"sv) { return makeGlobalSet(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'i': { - switch (buf[1]) { - case '1': { - switch (buf[6]) { - case 'a': { - switch (buf[7]) { - case 'b': - if (op == "i16x8.abs"sv) { return makeUnary(s, UnaryOp::AbsVecI16x8); } - goto parse_error; - case 'd': { - switch (buf[9]) { - case '\0': - if (op == "i16x8.add"sv) { return makeBinary(s, BinaryOp::AddVecI16x8); } - goto parse_error; - case '_': { - switch (buf[14]) { - case 's': - if (op == "i16x8.add_sat_s"sv) { return makeBinary(s, BinaryOp::AddSatSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.add_sat_u"sv) { return makeBinary(s, BinaryOp::AddSatUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'l': - if (op == "i16x8.all_true"sv) { return makeUnary(s, UnaryOp::AllTrueVecI16x8); } - goto parse_error; - case 'v': - if (op == "i16x8.avgr_u"sv) { return makeBinary(s, BinaryOp::AvgrUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'b': - if (op == "i16x8.bitmask"sv) { return makeUnary(s, UnaryOp::BitmaskVecI16x8); } - goto parse_error; - case 'd': - if (op == "i16x8.dot_i8x16_i7x16_s"sv) { return makeBinary(s, BinaryOp::DotI8x16I7x16SToVecI16x8); } - goto parse_error; - case 'e': { - switch (buf[7]) { - case 'q': - if (op == "i16x8.eq"sv) { return makeBinary(s, BinaryOp::EqVecI16x8); } - goto parse_error; - case 'x': { - switch (buf[9]) { - case 'a': { - switch (buf[28]) { - case 's': - if (op == "i16x8.extadd_pairwise_i8x16_s"sv) { return makeUnary(s, UnaryOp::ExtAddPairwiseSVecI8x16ToI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.extadd_pairwise_i8x16_u"sv) { return makeUnary(s, UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[13]) { - case 'h': { - switch (buf[24]) { - case 's': - if (op == "i16x8.extend_high_i8x16_s"sv) { return makeUnary(s, UnaryOp::ExtendHighSVecI8x16ToVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.extend_high_i8x16_u"sv) { return makeUnary(s, UnaryOp::ExtendHighUVecI8x16ToVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[23]) { - case 's': - if (op == "i16x8.extend_low_i8x16_s"sv) { return makeUnary(s, UnaryOp::ExtendLowSVecI8x16ToVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.extend_low_i8x16_u"sv) { return makeUnary(s, UnaryOp::ExtendLowUVecI8x16ToVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': { - switch (buf[13]) { - case 'h': { - switch (buf[24]) { - case 's': - if (op == "i16x8.extmul_high_i8x16_s"sv) { return makeBinary(s, BinaryOp::ExtMulHighSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.extmul_high_i8x16_u"sv) { return makeBinary(s, BinaryOp::ExtMulHighUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[23]) { - case 's': - if (op == "i16x8.extmul_low_i8x16_s"sv) { return makeBinary(s, BinaryOp::ExtMulLowSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.extmul_low_i8x16_u"sv) { return makeBinary(s, BinaryOp::ExtMulLowUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'r': { - switch (buf[19]) { - case 's': - if (op == "i16x8.extract_lane_s"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI16x8, 8); } - goto parse_error; - case 'u': - if (op == "i16x8.extract_lane_u"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI16x8, 8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'g': { - switch (buf[7]) { - case 'e': { - switch (buf[9]) { - case 's': - if (op == "i16x8.ge_s"sv) { return makeBinary(s, BinaryOp::GeSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.ge_u"sv) { return makeBinary(s, BinaryOp::GeUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[9]) { - case 's': - if (op == "i16x8.gt_s"sv) { return makeBinary(s, BinaryOp::GtSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.gt_u"sv) { return makeBinary(s, BinaryOp::GtUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'l': { - switch (buf[7]) { - case 'a': - if (op == "i16x8.laneselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI16x8); } - goto parse_error; - case 'e': { - switch (buf[9]) { - case 's': - if (op == "i16x8.le_s"sv) { return makeBinary(s, BinaryOp::LeSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.le_u"sv) { return makeBinary(s, BinaryOp::LeUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[9]) { - case 's': - if (op == "i16x8.lt_s"sv) { return makeBinary(s, BinaryOp::LtSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.lt_u"sv) { return makeBinary(s, BinaryOp::LtUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': { - switch (buf[7]) { - case 'a': { - switch (buf[10]) { - case 's': - if (op == "i16x8.max_s"sv) { return makeBinary(s, BinaryOp::MaxSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.max_u"sv) { return makeBinary(s, BinaryOp::MaxUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'i': { - switch (buf[10]) { - case 's': - if (op == "i16x8.min_s"sv) { return makeBinary(s, BinaryOp::MinSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.min_u"sv) { return makeBinary(s, BinaryOp::MinUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'u': - if (op == "i16x8.mul"sv) { return makeBinary(s, BinaryOp::MulVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': { - switch (buf[7]) { - case 'a': { - switch (buf[19]) { - case 's': - if (op == "i16x8.narrow_i32x4_s"sv) { return makeBinary(s, BinaryOp::NarrowSVecI32x4ToVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.narrow_i32x4_u"sv) { return makeBinary(s, BinaryOp::NarrowUVecI32x4ToVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[8]) { - case '\0': - if (op == "i16x8.ne"sv) { return makeBinary(s, BinaryOp::NeVecI16x8); } - goto parse_error; - case 'g': - if (op == "i16x8.neg"sv) { return makeUnary(s, UnaryOp::NegVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'q': - if (op == "i16x8.q15mulr_sat_s"sv) { return makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8); } - goto parse_error; - case 'r': { - switch (buf[8]) { - case 'l': - if (op == "i16x8.relaxed_q15mulr_s"sv) { return makeBinary(s, BinaryOp::RelaxedQ15MulrSVecI16x8); } - goto parse_error; - case 'p': - if (op == "i16x8.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI16x8, 8); } - goto parse_error; - default: goto parse_error; - } - } - case 's': { - switch (buf[7]) { - case 'h': { - switch (buf[8]) { - case 'l': - if (op == "i16x8.shl"sv) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI16x8); } - goto parse_error; - case 'r': { - switch (buf[10]) { - case 's': - if (op == "i16x8.shr_s"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.shr_u"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "i16x8.splat"sv) { return makeUnary(s, UnaryOp::SplatVecI16x8); } - goto parse_error; - case 'u': { - switch (buf[9]) { - case '\0': - if (op == "i16x8.sub"sv) { return makeBinary(s, BinaryOp::SubVecI16x8); } - goto parse_error; - case '_': { - switch (buf[14]) { - case 's': - if (op == "i16x8.sub_sat_s"sv) { return makeBinary(s, BinaryOp::SubSatSVecI16x8); } - goto parse_error; - case 'u': - if (op == "i16x8.sub_sat_u"sv) { return makeBinary(s, BinaryOp::SubSatUVecI16x8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '3': { - switch (buf[2]) { - case '1': { - switch (buf[4]) { - case 'g': { - switch (buf[8]) { - case 's': - if (op == "i31.get_s"sv) { return makeI31Get(s, true); } - goto parse_error; - case 'u': - if (op == "i31.get_u"sv) { return makeI31Get(s, false); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': - if (op == "i31.new"sv) { return makeRefI31(s); } - goto parse_error; - default: goto parse_error; - } - } - case '2': { - switch (buf[3]) { - case '.': { - switch (buf[4]) { - case 'a': { - switch (buf[5]) { - case 'd': - if (op == "i32.add"sv) { return makeBinary(s, BinaryOp::AddInt32); } - goto parse_error; - case 'n': - if (op == "i32.and"sv) { return makeBinary(s, BinaryOp::AndInt32); } - goto parse_error; - case 't': { - switch (buf[11]) { - case 'l': { - switch (buf[15]) { - case '\0': - if (op == "i32.atomic.load"sv) { return makeLoad(s, Type::i32, /*signed=*/false, 4, /*isAtomic=*/true); } - goto parse_error; - case '1': - if (op == "i32.atomic.load16_u"sv) { return makeLoad(s, Type::i32, /*signed=*/false, 2, /*isAtomic=*/true); } - goto parse_error; - case '8': - if (op == "i32.atomic.load8_u"sv) { return makeLoad(s, Type::i32, /*signed=*/false, 1, /*isAtomic=*/true); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': { - switch (buf[14]) { - case '.': { - switch (buf[15]) { - case 'a': { - switch (buf[16]) { - case 'd': - if (op == "i32.atomic.rmw.add"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i32, 4); } - goto parse_error; - case 'n': - if (op == "i32.atomic.rmw.and"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i32, 4); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': - if (op == "i32.atomic.rmw.cmpxchg"sv) { return makeAtomicCmpxchg(s, Type::i32, 4); } - goto parse_error; - case 'o': - if (op == "i32.atomic.rmw.or"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i32, 4); } - goto parse_error; - case 's': - if (op == "i32.atomic.rmw.sub"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i32, 4); } - goto parse_error; - case 'x': { - switch (buf[16]) { - case 'c': - if (op == "i32.atomic.rmw.xchg"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i32, 4); } - goto parse_error; - case 'o': - if (op == "i32.atomic.rmw.xor"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i32, 4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '1': { - switch (buf[17]) { - case 'a': { - switch (buf[18]) { - case 'd': - if (op == "i32.atomic.rmw16.add_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i32, 2); } - goto parse_error; - case 'n': - if (op == "i32.atomic.rmw16.and_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i32, 2); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': - if (op == "i32.atomic.rmw16.cmpxchg_u"sv) { return makeAtomicCmpxchg(s, Type::i32, 2); } - goto parse_error; - case 'o': - if (op == "i32.atomic.rmw16.or_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i32, 2); } - goto parse_error; - case 's': - if (op == "i32.atomic.rmw16.sub_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i32, 2); } - goto parse_error; - case 'x': { - switch (buf[18]) { - case 'c': - if (op == "i32.atomic.rmw16.xchg_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i32, 2); } - goto parse_error; - case 'o': - if (op == "i32.atomic.rmw16.xor_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i32, 2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '8': { - switch (buf[16]) { - case 'a': { - switch (buf[17]) { - case 'd': - if (op == "i32.atomic.rmw8.add_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i32, 1); } - goto parse_error; - case 'n': - if (op == "i32.atomic.rmw8.and_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i32, 1); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': - if (op == "i32.atomic.rmw8.cmpxchg_u"sv) { return makeAtomicCmpxchg(s, Type::i32, 1); } - goto parse_error; - case 'o': - if (op == "i32.atomic.rmw8.or_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i32, 1); } - goto parse_error; - case 's': - if (op == "i32.atomic.rmw8.sub_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i32, 1); } - goto parse_error; - case 'x': { - switch (buf[17]) { - case 'c': - if (op == "i32.atomic.rmw8.xchg_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i32, 1); } - goto parse_error; - case 'o': - if (op == "i32.atomic.rmw8.xor_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i32, 1); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 's': { - switch (buf[16]) { - case '\0': - if (op == "i32.atomic.store"sv) { return makeStore(s, Type::i32, 4, /*isAtomic=*/true); } - goto parse_error; - case '1': - if (op == "i32.atomic.store16"sv) { return makeStore(s, Type::i32, 2, /*isAtomic=*/true); } - goto parse_error; - case '8': - if (op == "i32.atomic.store8"sv) { return makeStore(s, Type::i32, 1, /*isAtomic=*/true); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'c': { - switch (buf[5]) { - case 'l': - if (op == "i32.clz"sv) { return makeUnary(s, UnaryOp::ClzInt32); } - goto parse_error; - case 'o': - if (op == "i32.const"sv) { return makeConst(s, Type::i32); } - goto parse_error; - case 't': - if (op == "i32.ctz"sv) { return makeUnary(s, UnaryOp::CtzInt32); } - goto parse_error; - default: goto parse_error; - } - } - case 'd': { - switch (buf[8]) { - case 's': - if (op == "i32.div_s"sv) { return makeBinary(s, BinaryOp::DivSInt32); } - goto parse_error; - case 'u': - if (op == "i32.div_u"sv) { return makeBinary(s, BinaryOp::DivUInt32); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[5]) { - case 'q': { - switch (buf[6]) { - case '\0': - if (op == "i32.eq"sv) { return makeBinary(s, BinaryOp::EqInt32); } - goto parse_error; - case 'z': - if (op == "i32.eqz"sv) { return makeUnary(s, UnaryOp::EqZInt32); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[10]) { - case '1': - if (op == "i32.extend16_s"sv) { return makeUnary(s, UnaryOp::ExtendS16Int32); } - goto parse_error; - case '8': - if (op == "i32.extend8_s"sv) { return makeUnary(s, UnaryOp::ExtendS8Int32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'g': { - switch (buf[5]) { - case 'e': { - switch (buf[7]) { - case 's': - if (op == "i32.ge_s"sv) { return makeBinary(s, BinaryOp::GeSInt32); } - goto parse_error; - case 'u': - if (op == "i32.ge_u"sv) { return makeBinary(s, BinaryOp::GeUInt32); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[7]) { - case 's': - if (op == "i32.gt_s"sv) { return makeBinary(s, BinaryOp::GtSInt32); } - goto parse_error; - case 'u': - if (op == "i32.gt_u"sv) { return makeBinary(s, BinaryOp::GtUInt32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'l': { - switch (buf[5]) { - case 'e': { - switch (buf[7]) { - case 's': - if (op == "i32.le_s"sv) { return makeBinary(s, BinaryOp::LeSInt32); } - goto parse_error; - case 'u': - if (op == "i32.le_u"sv) { return makeBinary(s, BinaryOp::LeUInt32); } - goto parse_error; - default: goto parse_error; - } - } - case 'o': { - switch (buf[8]) { - case '\0': - if (op == "i32.load"sv) { return makeLoad(s, Type::i32, /*signed=*/false, 4, /*isAtomic=*/false); } - goto parse_error; - case '1': { - switch (buf[11]) { - case 's': - if (op == "i32.load16_s"sv) { return makeLoad(s, Type::i32, /*signed=*/true, 2, /*isAtomic=*/false); } - goto parse_error; - case 'u': - if (op == "i32.load16_u"sv) { return makeLoad(s, Type::i32, /*signed=*/false, 2, /*isAtomic=*/false); } - goto parse_error; - default: goto parse_error; - } - } - case '8': { - switch (buf[10]) { - case 's': - if (op == "i32.load8_s"sv) { return makeLoad(s, Type::i32, /*signed=*/true, 1, /*isAtomic=*/false); } - goto parse_error; - case 'u': - if (op == "i32.load8_u"sv) { return makeLoad(s, Type::i32, /*signed=*/false, 1, /*isAtomic=*/false); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 't': { - switch (buf[7]) { - case 's': - if (op == "i32.lt_s"sv) { return makeBinary(s, BinaryOp::LtSInt32); } - goto parse_error; - case 'u': - if (op == "i32.lt_u"sv) { return makeBinary(s, BinaryOp::LtUInt32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': - if (op == "i32.mul"sv) { return makeBinary(s, BinaryOp::MulInt32); } - goto parse_error; - case 'n': - if (op == "i32.ne"sv) { return makeBinary(s, BinaryOp::NeInt32); } - goto parse_error; - case 'o': - if (op == "i32.or"sv) { return makeBinary(s, BinaryOp::OrInt32); } - goto parse_error; - case 'p': - if (op == "i32.popcnt"sv) { return makeUnary(s, UnaryOp::PopcntInt32); } - goto parse_error; - case 'r': { - switch (buf[5]) { - case 'e': { - switch (buf[6]) { - case 'i': - if (op == "i32.reinterpret_f32"sv) { return makeUnary(s, UnaryOp::ReinterpretFloat32); } - goto parse_error; - case 'm': { - switch (buf[8]) { - case 's': - if (op == "i32.rem_s"sv) { return makeBinary(s, BinaryOp::RemSInt32); } - goto parse_error; - case 'u': - if (op == "i32.rem_u"sv) { return makeBinary(s, BinaryOp::RemUInt32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'o': { - switch (buf[7]) { - case 'l': - if (op == "i32.rotl"sv) { return makeBinary(s, BinaryOp::RotLInt32); } - goto parse_error; - case 'r': - if (op == "i32.rotr"sv) { return makeBinary(s, BinaryOp::RotRInt32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 's': { - switch (buf[5]) { - case 'h': { - switch (buf[6]) { - case 'l': - if (op == "i32.shl"sv) { return makeBinary(s, BinaryOp::ShlInt32); } - goto parse_error; - case 'r': { - switch (buf[8]) { - case 's': - if (op == "i32.shr_s"sv) { return makeBinary(s, BinaryOp::ShrSInt32); } - goto parse_error; - case 'u': - if (op == "i32.shr_u"sv) { return makeBinary(s, BinaryOp::ShrUInt32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 't': { - switch (buf[9]) { - case '\0': - if (op == "i32.store"sv) { return makeStore(s, Type::i32, 4, /*isAtomic=*/false); } - goto parse_error; - case '1': - if (op == "i32.store16"sv) { return makeStore(s, Type::i32, 2, /*isAtomic=*/false); } - goto parse_error; - case '8': - if (op == "i32.store8"sv) { return makeStore(s, Type::i32, 1, /*isAtomic=*/false); } - goto parse_error; - default: goto parse_error; - } - } - case 'u': - if (op == "i32.sub"sv) { return makeBinary(s, BinaryOp::SubInt32); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[10]) { - case 'f': { - switch (buf[11]) { - case '3': { - switch (buf[14]) { - case 's': - if (op == "i32.trunc_f32_s"sv) { return makeUnary(s, UnaryOp::TruncSFloat32ToInt32); } - goto parse_error; - case 'u': - if (op == "i32.trunc_f32_u"sv) { return makeUnary(s, UnaryOp::TruncUFloat32ToInt32); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (buf[14]) { - case 's': - if (op == "i32.trunc_f64_s"sv) { return makeUnary(s, UnaryOp::TruncSFloat64ToInt32); } - goto parse_error; - case 'u': - if (op == "i32.trunc_f64_u"sv) { return makeUnary(s, UnaryOp::TruncUFloat64ToInt32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 's': { - switch (buf[15]) { - case '3': { - switch (buf[18]) { - case 's': - if (op == "i32.trunc_sat_f32_s"sv) { return makeUnary(s, UnaryOp::TruncSatSFloat32ToInt32); } - goto parse_error; - case 'u': - if (op == "i32.trunc_sat_f32_u"sv) { return makeUnary(s, UnaryOp::TruncSatUFloat32ToInt32); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (buf[18]) { - case 's': - if (op == "i32.trunc_sat_f64_s"sv) { return makeUnary(s, UnaryOp::TruncSatSFloat64ToInt32); } - goto parse_error; - case 'u': - if (op == "i32.trunc_sat_f64_u"sv) { return makeUnary(s, UnaryOp::TruncSatUFloat64ToInt32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'w': - if (op == "i32.wrap_i64"sv) { return makeUnary(s, UnaryOp::WrapInt64); } - goto parse_error; - case 'x': - if (op == "i32.xor"sv) { return makeBinary(s, BinaryOp::XorInt32); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[6]) { - case 'a': { - switch (buf[7]) { - case 'b': - if (op == "i32x4.abs"sv) { return makeUnary(s, UnaryOp::AbsVecI32x4); } - goto parse_error; - case 'd': - if (op == "i32x4.add"sv) { return makeBinary(s, BinaryOp::AddVecI32x4); } - goto parse_error; - case 'l': - if (op == "i32x4.all_true"sv) { return makeUnary(s, UnaryOp::AllTrueVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'b': - if (op == "i32x4.bitmask"sv) { return makeUnary(s, UnaryOp::BitmaskVecI32x4); } - goto parse_error; - case 'd': { - switch (buf[11]) { - case '1': - if (op == "i32x4.dot_i16x8_s"sv) { return makeBinary(s, BinaryOp::DotSVecI16x8ToVecI32x4); } - goto parse_error; - case '8': - if (op == "i32x4.dot_i8x16_i7x16_add_s"sv) { return makeSIMDTernary(s, SIMDTernaryOp::DotI8x16I7x16AddSToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[7]) { - case 'q': - if (op == "i32x4.eq"sv) { return makeBinary(s, BinaryOp::EqVecI32x4); } - goto parse_error; - case 'x': { - switch (buf[9]) { - case 'a': { - switch (buf[28]) { - case 's': - if (op == "i32x4.extadd_pairwise_i16x8_s"sv) { return makeUnary(s, UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.extadd_pairwise_i16x8_u"sv) { return makeUnary(s, UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[13]) { - case 'h': { - switch (buf[24]) { - case 's': - if (op == "i32x4.extend_high_i16x8_s"sv) { return makeUnary(s, UnaryOp::ExtendHighSVecI16x8ToVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.extend_high_i16x8_u"sv) { return makeUnary(s, UnaryOp::ExtendHighUVecI16x8ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[23]) { - case 's': - if (op == "i32x4.extend_low_i16x8_s"sv) { return makeUnary(s, UnaryOp::ExtendLowSVecI16x8ToVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.extend_low_i16x8_u"sv) { return makeUnary(s, UnaryOp::ExtendLowUVecI16x8ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': { - switch (buf[13]) { - case 'h': { - switch (buf[24]) { - case 's': - if (op == "i32x4.extmul_high_i16x8_s"sv) { return makeBinary(s, BinaryOp::ExtMulHighSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.extmul_high_i16x8_u"sv) { return makeBinary(s, BinaryOp::ExtMulHighUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[23]) { - case 's': - if (op == "i32x4.extmul_low_i16x8_s"sv) { return makeBinary(s, BinaryOp::ExtMulLowSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.extmul_low_i16x8_u"sv) { return makeBinary(s, BinaryOp::ExtMulLowUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'r': - if (op == "i32x4.extract_lane"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI32x4, 4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'g': { - switch (buf[7]) { - case 'e': { - switch (buf[9]) { - case 's': - if (op == "i32x4.ge_s"sv) { return makeBinary(s, BinaryOp::GeSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.ge_u"sv) { return makeBinary(s, BinaryOp::GeUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[9]) { - case 's': - if (op == "i32x4.gt_s"sv) { return makeBinary(s, BinaryOp::GtSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.gt_u"sv) { return makeBinary(s, BinaryOp::GtUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'l': { - switch (buf[7]) { - case 'a': - if (op == "i32x4.laneselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI32x4); } - goto parse_error; - case 'e': { - switch (buf[9]) { - case 's': - if (op == "i32x4.le_s"sv) { return makeBinary(s, BinaryOp::LeSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.le_u"sv) { return makeBinary(s, BinaryOp::LeUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[9]) { - case 's': - if (op == "i32x4.lt_s"sv) { return makeBinary(s, BinaryOp::LtSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.lt_u"sv) { return makeBinary(s, BinaryOp::LtUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': { - switch (buf[7]) { - case 'a': { - switch (buf[10]) { - case 's': - if (op == "i32x4.max_s"sv) { return makeBinary(s, BinaryOp::MaxSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.max_u"sv) { return makeBinary(s, BinaryOp::MaxUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'i': { - switch (buf[10]) { - case 's': - if (op == "i32x4.min_s"sv) { return makeBinary(s, BinaryOp::MinSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.min_u"sv) { return makeBinary(s, BinaryOp::MinUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'u': - if (op == "i32x4.mul"sv) { return makeBinary(s, BinaryOp::MulVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': { - switch (buf[8]) { - case '\0': - if (op == "i32x4.ne"sv) { return makeBinary(s, BinaryOp::NeVecI32x4); } - goto parse_error; - case 'g': - if (op == "i32x4.neg"sv) { return makeUnary(s, UnaryOp::NegVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': { - switch (buf[8]) { - case 'l': { - switch (buf[21]) { - case '3': { - switch (buf[26]) { - case 's': - if (op == "i32x4.relaxed_trunc_f32x4_s"sv) { return makeUnary(s, UnaryOp::RelaxedTruncSVecF32x4ToVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.relaxed_trunc_f32x4_u"sv) { return makeUnary(s, UnaryOp::RelaxedTruncUVecF32x4ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (buf[26]) { - case 's': - if (op == "i32x4.relaxed_trunc_f64x2_s_zero"sv) { return makeUnary(s, UnaryOp::RelaxedTruncZeroSVecF64x2ToVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.relaxed_trunc_f64x2_u_zero"sv) { return makeUnary(s, UnaryOp::RelaxedTruncZeroUVecF64x2ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "i32x4.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI32x4, 4); } - goto parse_error; - default: goto parse_error; - } - } - case 's': { - switch (buf[7]) { - case 'h': { - switch (buf[8]) { - case 'l': - if (op == "i32x4.shl"sv) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI32x4); } - goto parse_error; - case 'r': { - switch (buf[10]) { - case 's': - if (op == "i32x4.shr_s"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.shr_u"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "i32x4.splat"sv) { return makeUnary(s, UnaryOp::SplatVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.sub"sv) { return makeBinary(s, BinaryOp::SubVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[17]) { - case '3': { - switch (buf[22]) { - case 's': - if (op == "i32x4.trunc_sat_f32x4_s"sv) { return makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.trunc_sat_f32x4_u"sv) { return makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (buf[22]) { - case 's': - if (op == "i32x4.trunc_sat_f64x2_s_zero"sv) { return makeUnary(s, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4); } - goto parse_error; - case 'u': - if (op == "i32x4.trunc_sat_f64x2_u_zero"sv) { return makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '6': { - switch (buf[3]) { - case '.': { - switch (buf[4]) { - case 'a': { - switch (buf[5]) { - case 'd': - if (op == "i64.add"sv) { return makeBinary(s, BinaryOp::AddInt64); } - goto parse_error; - case 'n': - if (op == "i64.and"sv) { return makeBinary(s, BinaryOp::AndInt64); } - goto parse_error; - case 't': { - switch (buf[11]) { - case 'l': { - switch (buf[15]) { - case '\0': - if (op == "i64.atomic.load"sv) { return makeLoad(s, Type::i64, /*signed=*/false, 8, /*isAtomic=*/true); } - goto parse_error; - case '1': - if (op == "i64.atomic.load16_u"sv) { return makeLoad(s, Type::i64, /*signed=*/false, 2, /*isAtomic=*/true); } - goto parse_error; - case '3': - if (op == "i64.atomic.load32_u"sv) { return makeLoad(s, Type::i64, /*signed=*/false, 4, /*isAtomic=*/true); } - goto parse_error; - case '8': - if (op == "i64.atomic.load8_u"sv) { return makeLoad(s, Type::i64, /*signed=*/false, 1, /*isAtomic=*/true); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': { - switch (buf[14]) { - case '.': { - switch (buf[15]) { - case 'a': { - switch (buf[16]) { - case 'd': - if (op == "i64.atomic.rmw.add"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i64, 8); } - goto parse_error; - case 'n': - if (op == "i64.atomic.rmw.and"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i64, 8); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': - if (op == "i64.atomic.rmw.cmpxchg"sv) { return makeAtomicCmpxchg(s, Type::i64, 8); } - goto parse_error; - case 'o': - if (op == "i64.atomic.rmw.or"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i64, 8); } - goto parse_error; - case 's': - if (op == "i64.atomic.rmw.sub"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i64, 8); } - goto parse_error; - case 'x': { - switch (buf[16]) { - case 'c': - if (op == "i64.atomic.rmw.xchg"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i64, 8); } - goto parse_error; - case 'o': - if (op == "i64.atomic.rmw.xor"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i64, 8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '1': { - switch (buf[17]) { - case 'a': { - switch (buf[18]) { - case 'd': - if (op == "i64.atomic.rmw16.add_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i64, 2); } - goto parse_error; - case 'n': - if (op == "i64.atomic.rmw16.and_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i64, 2); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': - if (op == "i64.atomic.rmw16.cmpxchg_u"sv) { return makeAtomicCmpxchg(s, Type::i64, 2); } - goto parse_error; - case 'o': - if (op == "i64.atomic.rmw16.or_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i64, 2); } - goto parse_error; - case 's': - if (op == "i64.atomic.rmw16.sub_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i64, 2); } - goto parse_error; - case 'x': { - switch (buf[18]) { - case 'c': - if (op == "i64.atomic.rmw16.xchg_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i64, 2); } - goto parse_error; - case 'o': - if (op == "i64.atomic.rmw16.xor_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i64, 2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '3': { - switch (buf[17]) { - case 'a': { - switch (buf[18]) { - case 'd': - if (op == "i64.atomic.rmw32.add_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i64, 4); } - goto parse_error; - case 'n': - if (op == "i64.atomic.rmw32.and_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i64, 4); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': - if (op == "i64.atomic.rmw32.cmpxchg_u"sv) { return makeAtomicCmpxchg(s, Type::i64, 4); } - goto parse_error; - case 'o': - if (op == "i64.atomic.rmw32.or_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i64, 4); } - goto parse_error; - case 's': - if (op == "i64.atomic.rmw32.sub_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i64, 4); } - goto parse_error; - case 'x': { - switch (buf[18]) { - case 'c': - if (op == "i64.atomic.rmw32.xchg_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i64, 4); } - goto parse_error; - case 'o': - if (op == "i64.atomic.rmw32.xor_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i64, 4); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '8': { - switch (buf[16]) { - case 'a': { - switch (buf[17]) { - case 'd': - if (op == "i64.atomic.rmw8.add_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAdd, Type::i64, 1); } - goto parse_error; - case 'n': - if (op == "i64.atomic.rmw8.and_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWAnd, Type::i64, 1); } - goto parse_error; - default: goto parse_error; - } - } - case 'c': - if (op == "i64.atomic.rmw8.cmpxchg_u"sv) { return makeAtomicCmpxchg(s, Type::i64, 1); } - goto parse_error; - case 'o': - if (op == "i64.atomic.rmw8.or_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWOr, Type::i64, 1); } - goto parse_error; - case 's': - if (op == "i64.atomic.rmw8.sub_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWSub, Type::i64, 1); } - goto parse_error; - case 'x': { - switch (buf[17]) { - case 'c': - if (op == "i64.atomic.rmw8.xchg_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXchg, Type::i64, 1); } - goto parse_error; - case 'o': - if (op == "i64.atomic.rmw8.xor_u"sv) { return makeAtomicRMW(s, AtomicRMWOp::RMWXor, Type::i64, 1); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 's': { - switch (buf[16]) { - case '\0': - if (op == "i64.atomic.store"sv) { return makeStore(s, Type::i64, 8, /*isAtomic=*/true); } - goto parse_error; - case '1': - if (op == "i64.atomic.store16"sv) { return makeStore(s, Type::i64, 2, /*isAtomic=*/true); } - goto parse_error; - case '3': - if (op == "i64.atomic.store32"sv) { return makeStore(s, Type::i64, 4, /*isAtomic=*/true); } - goto parse_error; - case '8': - if (op == "i64.atomic.store8"sv) { return makeStore(s, Type::i64, 1, /*isAtomic=*/true); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'c': { - switch (buf[5]) { - case 'l': - if (op == "i64.clz"sv) { return makeUnary(s, UnaryOp::ClzInt64); } - goto parse_error; - case 'o': - if (op == "i64.const"sv) { return makeConst(s, Type::i64); } - goto parse_error; - case 't': - if (op == "i64.ctz"sv) { return makeUnary(s, UnaryOp::CtzInt64); } - goto parse_error; - default: goto parse_error; - } - } - case 'd': { - switch (buf[8]) { - case 's': - if (op == "i64.div_s"sv) { return makeBinary(s, BinaryOp::DivSInt64); } - goto parse_error; - case 'u': - if (op == "i64.div_u"sv) { return makeBinary(s, BinaryOp::DivUInt64); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[5]) { - case 'q': { - switch (buf[6]) { - case '\0': - if (op == "i64.eq"sv) { return makeBinary(s, BinaryOp::EqInt64); } - goto parse_error; - case 'z': - if (op == "i64.eqz"sv) { return makeUnary(s, UnaryOp::EqZInt64); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[10]) { - case '1': - if (op == "i64.extend16_s"sv) { return makeUnary(s, UnaryOp::ExtendS16Int64); } - goto parse_error; - case '3': - if (op == "i64.extend32_s"sv) { return makeUnary(s, UnaryOp::ExtendS32Int64); } - goto parse_error; - case '8': - if (op == "i64.extend8_s"sv) { return makeUnary(s, UnaryOp::ExtendS8Int64); } - goto parse_error; - case '_': { - switch (buf[15]) { - case 's': - if (op == "i64.extend_i32_s"sv) { return makeUnary(s, UnaryOp::ExtendSInt32); } - goto parse_error; - case 'u': - if (op == "i64.extend_i32_u"sv) { return makeUnary(s, UnaryOp::ExtendUInt32); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'g': { - switch (buf[5]) { - case 'e': { - switch (buf[7]) { - case 's': - if (op == "i64.ge_s"sv) { return makeBinary(s, BinaryOp::GeSInt64); } - goto parse_error; - case 'u': - if (op == "i64.ge_u"sv) { return makeBinary(s, BinaryOp::GeUInt64); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[7]) { - case 's': - if (op == "i64.gt_s"sv) { return makeBinary(s, BinaryOp::GtSInt64); } - goto parse_error; - case 'u': - if (op == "i64.gt_u"sv) { return makeBinary(s, BinaryOp::GtUInt64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'l': { - switch (buf[5]) { - case 'e': { - switch (buf[7]) { - case 's': - if (op == "i64.le_s"sv) { return makeBinary(s, BinaryOp::LeSInt64); } - goto parse_error; - case 'u': - if (op == "i64.le_u"sv) { return makeBinary(s, BinaryOp::LeUInt64); } - goto parse_error; - default: goto parse_error; - } - } - case 'o': { - switch (buf[8]) { - case '\0': - if (op == "i64.load"sv) { return makeLoad(s, Type::i64, /*signed=*/false, 8, /*isAtomic=*/false); } - goto parse_error; - case '1': { - switch (buf[11]) { - case 's': - if (op == "i64.load16_s"sv) { return makeLoad(s, Type::i64, /*signed=*/true, 2, /*isAtomic=*/false); } - goto parse_error; - case 'u': - if (op == "i64.load16_u"sv) { return makeLoad(s, Type::i64, /*signed=*/false, 2, /*isAtomic=*/false); } - goto parse_error; - default: goto parse_error; - } - } - case '3': { - switch (buf[11]) { - case 's': - if (op == "i64.load32_s"sv) { return makeLoad(s, Type::i64, /*signed=*/true, 4, /*isAtomic=*/false); } - goto parse_error; - case 'u': - if (op == "i64.load32_u"sv) { return makeLoad(s, Type::i64, /*signed=*/false, 4, /*isAtomic=*/false); } - goto parse_error; - default: goto parse_error; - } - } - case '8': { - switch (buf[10]) { - case 's': - if (op == "i64.load8_s"sv) { return makeLoad(s, Type::i64, /*signed=*/true, 1, /*isAtomic=*/false); } - goto parse_error; - case 'u': - if (op == "i64.load8_u"sv) { return makeLoad(s, Type::i64, /*signed=*/false, 1, /*isAtomic=*/false); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 't': { - switch (buf[7]) { - case 's': - if (op == "i64.lt_s"sv) { return makeBinary(s, BinaryOp::LtSInt64); } - goto parse_error; - case 'u': - if (op == "i64.lt_u"sv) { return makeBinary(s, BinaryOp::LtUInt64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': - if (op == "i64.mul"sv) { return makeBinary(s, BinaryOp::MulInt64); } - goto parse_error; - case 'n': - if (op == "i64.ne"sv) { return makeBinary(s, BinaryOp::NeInt64); } - goto parse_error; - case 'o': - if (op == "i64.or"sv) { return makeBinary(s, BinaryOp::OrInt64); } - goto parse_error; - case 'p': - if (op == "i64.popcnt"sv) { return makeUnary(s, UnaryOp::PopcntInt64); } - goto parse_error; - case 'r': { - switch (buf[5]) { - case 'e': { - switch (buf[6]) { - case 'i': - if (op == "i64.reinterpret_f64"sv) { return makeUnary(s, UnaryOp::ReinterpretFloat64); } - goto parse_error; - case 'm': { - switch (buf[8]) { - case 's': - if (op == "i64.rem_s"sv) { return makeBinary(s, BinaryOp::RemSInt64); } - goto parse_error; - case 'u': - if (op == "i64.rem_u"sv) { return makeBinary(s, BinaryOp::RemUInt64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'o': { - switch (buf[7]) { - case 'l': - if (op == "i64.rotl"sv) { return makeBinary(s, BinaryOp::RotLInt64); } - goto parse_error; - case 'r': - if (op == "i64.rotr"sv) { return makeBinary(s, BinaryOp::RotRInt64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 's': { - switch (buf[5]) { - case 'h': { - switch (buf[6]) { - case 'l': - if (op == "i64.shl"sv) { return makeBinary(s, BinaryOp::ShlInt64); } - goto parse_error; - case 'r': { - switch (buf[8]) { - case 's': - if (op == "i64.shr_s"sv) { return makeBinary(s, BinaryOp::ShrSInt64); } - goto parse_error; - case 'u': - if (op == "i64.shr_u"sv) { return makeBinary(s, BinaryOp::ShrUInt64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 't': { - switch (buf[9]) { - case '\0': - if (op == "i64.store"sv) { return makeStore(s, Type::i64, 8, /*isAtomic=*/false); } - goto parse_error; - case '1': - if (op == "i64.store16"sv) { return makeStore(s, Type::i64, 2, /*isAtomic=*/false); } - goto parse_error; - case '3': - if (op == "i64.store32"sv) { return makeStore(s, Type::i64, 4, /*isAtomic=*/false); } - goto parse_error; - case '8': - if (op == "i64.store8"sv) { return makeStore(s, Type::i64, 1, /*isAtomic=*/false); } - goto parse_error; - default: goto parse_error; - } - } - case 'u': - if (op == "i64.sub"sv) { return makeBinary(s, BinaryOp::SubInt64); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[10]) { - case 'f': { - switch (buf[11]) { - case '3': { - switch (buf[14]) { - case 's': - if (op == "i64.trunc_f32_s"sv) { return makeUnary(s, UnaryOp::TruncSFloat32ToInt64); } - goto parse_error; - case 'u': - if (op == "i64.trunc_f32_u"sv) { return makeUnary(s, UnaryOp::TruncUFloat32ToInt64); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (buf[14]) { - case 's': - if (op == "i64.trunc_f64_s"sv) { return makeUnary(s, UnaryOp::TruncSFloat64ToInt64); } - goto parse_error; - case 'u': - if (op == "i64.trunc_f64_u"sv) { return makeUnary(s, UnaryOp::TruncUFloat64ToInt64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 's': { - switch (buf[15]) { - case '3': { - switch (buf[18]) { - case 's': - if (op == "i64.trunc_sat_f32_s"sv) { return makeUnary(s, UnaryOp::TruncSatSFloat32ToInt64); } - goto parse_error; - case 'u': - if (op == "i64.trunc_sat_f32_u"sv) { return makeUnary(s, UnaryOp::TruncSatUFloat32ToInt64); } - goto parse_error; - default: goto parse_error; - } - } - case '6': { - switch (buf[18]) { - case 's': - if (op == "i64.trunc_sat_f64_s"sv) { return makeUnary(s, UnaryOp::TruncSatSFloat64ToInt64); } - goto parse_error; - case 'u': - if (op == "i64.trunc_sat_f64_u"sv) { return makeUnary(s, UnaryOp::TruncSatUFloat64ToInt64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'x': - if (op == "i64.xor"sv) { return makeBinary(s, BinaryOp::XorInt64); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[6]) { - case 'a': { - switch (buf[7]) { - case 'b': - if (op == "i64x2.abs"sv) { return makeUnary(s, UnaryOp::AbsVecI64x2); } - goto parse_error; - case 'd': - if (op == "i64x2.add"sv) { return makeBinary(s, BinaryOp::AddVecI64x2); } - goto parse_error; - case 'l': - if (op == "i64x2.all_true"sv) { return makeUnary(s, UnaryOp::AllTrueVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'b': - if (op == "i64x2.bitmask"sv) { return makeUnary(s, UnaryOp::BitmaskVecI64x2); } - goto parse_error; - case 'e': { - switch (buf[7]) { - case 'q': - if (op == "i64x2.eq"sv) { return makeBinary(s, BinaryOp::EqVecI64x2); } - goto parse_error; - case 'x': { - switch (buf[9]) { - case 'e': { - switch (buf[13]) { - case 'h': { - switch (buf[24]) { - case 's': - if (op == "i64x2.extend_high_i32x4_s"sv) { return makeUnary(s, UnaryOp::ExtendHighSVecI32x4ToVecI64x2); } - goto parse_error; - case 'u': - if (op == "i64x2.extend_high_i32x4_u"sv) { return makeUnary(s, UnaryOp::ExtendHighUVecI32x4ToVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[23]) { - case 's': - if (op == "i64x2.extend_low_i32x4_s"sv) { return makeUnary(s, UnaryOp::ExtendLowSVecI32x4ToVecI64x2); } - goto parse_error; - case 'u': - if (op == "i64x2.extend_low_i32x4_u"sv) { return makeUnary(s, UnaryOp::ExtendLowUVecI32x4ToVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': { - switch (buf[13]) { - case 'h': { - switch (buf[24]) { - case 's': - if (op == "i64x2.extmul_high_i32x4_s"sv) { return makeBinary(s, BinaryOp::ExtMulHighSVecI64x2); } - goto parse_error; - case 'u': - if (op == "i64x2.extmul_high_i32x4_u"sv) { return makeBinary(s, BinaryOp::ExtMulHighUVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[23]) { - case 's': - if (op == "i64x2.extmul_low_i32x4_s"sv) { return makeBinary(s, BinaryOp::ExtMulLowSVecI64x2); } - goto parse_error; - case 'u': - if (op == "i64x2.extmul_low_i32x4_u"sv) { return makeBinary(s, BinaryOp::ExtMulLowUVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'r': - if (op == "i64x2.extract_lane"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI64x2, 2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'g': { - switch (buf[7]) { - case 'e': - if (op == "i64x2.ge_s"sv) { return makeBinary(s, BinaryOp::GeSVecI64x2); } - goto parse_error; - case 't': - if (op == "i64x2.gt_s"sv) { return makeBinary(s, BinaryOp::GtSVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[7]) { - case 'a': - if (op == "i64x2.laneselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI64x2); } - goto parse_error; - case 'e': - if (op == "i64x2.le_s"sv) { return makeBinary(s, BinaryOp::LeSVecI64x2); } - goto parse_error; - case 't': - if (op == "i64x2.lt_s"sv) { return makeBinary(s, BinaryOp::LtSVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': - if (op == "i64x2.mul"sv) { return makeBinary(s, BinaryOp::MulVecI64x2); } - goto parse_error; - case 'n': { - switch (buf[8]) { - case '\0': - if (op == "i64x2.ne"sv) { return makeBinary(s, BinaryOp::NeVecI64x2); } - goto parse_error; - case 'g': - if (op == "i64x2.neg"sv) { return makeUnary(s, UnaryOp::NegVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - case 'r': - if (op == "i64x2.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI64x2, 2); } - goto parse_error; - case 's': { - switch (buf[7]) { - case 'h': { - switch (buf[8]) { - case 'l': - if (op == "i64x2.shl"sv) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI64x2); } - goto parse_error; - case 'r': { - switch (buf[10]) { - case 's': - if (op == "i64x2.shr_s"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI64x2); } - goto parse_error; - case 'u': - if (op == "i64x2.shr_u"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "i64x2.splat"sv) { return makeUnary(s, UnaryOp::SplatVecI64x2); } - goto parse_error; - case 'u': - if (op == "i64x2.sub"sv) { return makeBinary(s, BinaryOp::SubVecI64x2); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '8': { - switch (buf[6]) { - case 'a': { - switch (buf[7]) { - case 'b': - if (op == "i8x16.abs"sv) { return makeUnary(s, UnaryOp::AbsVecI8x16); } - goto parse_error; - case 'd': { - switch (buf[9]) { - case '\0': - if (op == "i8x16.add"sv) { return makeBinary(s, BinaryOp::AddVecI8x16); } - goto parse_error; - case '_': { - switch (buf[14]) { - case 's': - if (op == "i8x16.add_sat_s"sv) { return makeBinary(s, BinaryOp::AddSatSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.add_sat_u"sv) { return makeBinary(s, BinaryOp::AddSatUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'l': - if (op == "i8x16.all_true"sv) { return makeUnary(s, UnaryOp::AllTrueVecI8x16); } - goto parse_error; - case 'v': - if (op == "i8x16.avgr_u"sv) { return makeBinary(s, BinaryOp::AvgrUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - case 'b': - if (op == "i8x16.bitmask"sv) { return makeUnary(s, UnaryOp::BitmaskVecI8x16); } - goto parse_error; - case 'e': { - switch (buf[7]) { - case 'q': - if (op == "i8x16.eq"sv) { return makeBinary(s, BinaryOp::EqVecI8x16); } - goto parse_error; - case 'x': { - switch (buf[19]) { - case 's': - if (op == "i8x16.extract_lane_s"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI8x16, 16); } - goto parse_error; - case 'u': - if (op == "i8x16.extract_lane_u"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI8x16, 16); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'g': { - switch (buf[7]) { - case 'e': { - switch (buf[9]) { - case 's': - if (op == "i8x16.ge_s"sv) { return makeBinary(s, BinaryOp::GeSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.ge_u"sv) { return makeBinary(s, BinaryOp::GeUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[9]) { - case 's': - if (op == "i8x16.gt_s"sv) { return makeBinary(s, BinaryOp::GtSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.gt_u"sv) { return makeBinary(s, BinaryOp::GtUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'l': { - switch (buf[7]) { - case 'a': - if (op == "i8x16.laneselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI8x16); } - goto parse_error; - case 'e': { - switch (buf[9]) { - case 's': - if (op == "i8x16.le_s"sv) { return makeBinary(s, BinaryOp::LeSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.le_u"sv) { return makeBinary(s, BinaryOp::LeUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[9]) { - case 's': - if (op == "i8x16.lt_s"sv) { return makeBinary(s, BinaryOp::LtSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.lt_u"sv) { return makeBinary(s, BinaryOp::LtUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'm': { - switch (buf[7]) { - case 'a': { - switch (buf[10]) { - case 's': - if (op == "i8x16.max_s"sv) { return makeBinary(s, BinaryOp::MaxSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.max_u"sv) { return makeBinary(s, BinaryOp::MaxUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - case 'i': { - switch (buf[10]) { - case 's': - if (op == "i8x16.min_s"sv) { return makeBinary(s, BinaryOp::MinSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.min_u"sv) { return makeBinary(s, BinaryOp::MinUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'n': { - switch (buf[7]) { - case 'a': { - switch (buf[19]) { - case 's': - if (op == "i8x16.narrow_i16x8_s"sv) { return makeBinary(s, BinaryOp::NarrowSVecI16x8ToVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.narrow_i16x8_u"sv) { return makeBinary(s, BinaryOp::NarrowUVecI16x8ToVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - case 'e': { - switch (buf[8]) { - case '\0': - if (op == "i8x16.ne"sv) { return makeBinary(s, BinaryOp::NeVecI8x16); } - goto parse_error; - case 'g': - if (op == "i8x16.neg"sv) { return makeUnary(s, UnaryOp::NegVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'p': - if (op == "i8x16.popcnt"sv) { return makeUnary(s, UnaryOp::PopcntVecI8x16); } - goto parse_error; - case 'r': { - switch (buf[8]) { - case 'l': - if (op == "i8x16.relaxed_swizzle"sv) { return makeBinary(s, BinaryOp::RelaxedSwizzleVecI8x16); } - goto parse_error; - case 'p': - if (op == "i8x16.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI8x16, 16); } - goto parse_error; - default: goto parse_error; - } - } - case 's': { - switch (buf[7]) { - case 'h': { - switch (buf[8]) { - case 'l': - if (op == "i8x16.shl"sv) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI8x16); } - goto parse_error; - case 'r': { - switch (buf[10]) { - case 's': - if (op == "i8x16.shr_s"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.shr_u"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - case 'u': - if (op == "i8x16.shuffle"sv) { return makeSIMDShuffle(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'p': - if (op == "i8x16.splat"sv) { return makeUnary(s, UnaryOp::SplatVecI8x16); } - goto parse_error; - case 'u': { - switch (buf[9]) { - case '\0': - if (op == "i8x16.sub"sv) { return makeBinary(s, BinaryOp::SubVecI8x16); } - goto parse_error; - case '_': { - switch (buf[14]) { - case 's': - if (op == "i8x16.sub_sat_s"sv) { return makeBinary(s, BinaryOp::SubSatSVecI8x16); } - goto parse_error; - case 'u': - if (op == "i8x16.sub_sat_u"sv) { return makeBinary(s, BinaryOp::SubSatUVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'w': - if (op == "i8x16.swizzle"sv) { return makeBinary(s, BinaryOp::SwizzleVecI8x16); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'f': - if (op == "if"sv) { return makeIf(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'l': { - switch (buf[2]) { - case 'c': { - switch (buf[6]) { - case 'g': - if (op == "local.get"sv) { return makeLocalGet(s); } - goto parse_error; - case 's': - if (op == "local.set"sv) { return makeLocalSet(s); } - goto parse_error; - case 't': - if (op == "local.tee"sv) { return makeLocalTee(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'o': - if (op == "loop"sv) { return makeLoop(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'm': { - switch (buf[7]) { - case 'a': { - switch (buf[14]) { - case 'n': - if (op == "memory.atomic.notify"sv) { return makeAtomicNotify(s); } - goto parse_error; - case 'w': { - switch (buf[18]) { - case '3': - if (op == "memory.atomic.wait32"sv) { return makeAtomicWait(s, Type::i32); } - goto parse_error; - case '6': - if (op == "memory.atomic.wait64"sv) { return makeAtomicWait(s, Type::i64); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'c': - if (op == "memory.copy"sv) { return makeMemoryCopy(s); } - goto parse_error; - case 'f': - if (op == "memory.fill"sv) { return makeMemoryFill(s); } - goto parse_error; - case 'g': - if (op == "memory.grow"sv) { return makeMemoryGrow(s); } - goto parse_error; - case 'i': - if (op == "memory.init"sv) { return makeMemoryInit(s); } - goto parse_error; - case 's': - if (op == "memory.size"sv) { return makeMemorySize(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': - if (op == "nop"sv) { return makeNop(); } - goto parse_error; - case 'p': - if (op == "pop"sv) { return makePop(s); } - goto parse_error; - case 'r': { - switch (buf[2]) { - case 'f': { - switch (buf[4]) { - case 'a': - if (op == "ref.as_non_null"sv) { return makeRefAs(s, RefAsNonNull); } - goto parse_error; - case 'c': - if (op == "ref.cast"sv) { return makeRefCast(s); } - goto parse_error; - case 'e': - if (op == "ref.eq"sv) { return makeRefEq(s); } - goto parse_error; - case 'f': - if (op == "ref.func"sv) { return makeRefFunc(s); } - goto parse_error; - case 'i': { - switch (buf[5]) { - case '3': - if (op == "ref.i31"sv) { return makeRefI31(s); } - goto parse_error; - case 's': - if (op == "ref.is_null"sv) { return makeRefIsNull(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': - if (op == "ref.null"sv) { return makeRefNull(s); } - goto parse_error; - case 't': - if (op == "ref.test"sv) { return makeRefTest(s); } - goto parse_error; - default: goto parse_error; - } - } - case 's': - if (op == "resume"sv) { return makeResume(s); } - goto parse_error; - case 't': { - switch (buf[3]) { - case 'h': - if (op == "rethrow"sv) { return makeRethrow(s); } - goto parse_error; - case 'u': { - switch (buf[6]) { - case '\0': - if (op == "return"sv) { return makeReturn(s); } - goto parse_error; - case '_': { - switch (buf[11]) { - case '\0': - if (op == "return_call"sv) { return makeCall(s, /*isReturn=*/true); } - goto parse_error; - case '_': { - switch (buf[12]) { - case 'i': - if (op == "return_call_indirect"sv) { return makeCallIndirect(s, /*isReturn=*/true); } - goto parse_error; - case 'r': - if (op == "return_call_ref"sv) { return makeCallRef(s, /*isReturn=*/true); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 's': { - switch (buf[1]) { - case 'e': - if (op == "select"sv) { return makeSelect(s); } - goto parse_error; - case 't': { - switch (buf[3]) { - case 'i': { - switch (buf[6]) { - case '.': { - switch (buf[7]) { - case 'a': - if (op == "string.as_wtf16"sv) { return ignore(s); } - goto parse_error; - case 'c': { - switch (buf[9]) { - case 'm': - if (op == "string.compare"sv) { return makeStringEq(s, StringEqCompare); } - goto parse_error; - case 'n': { - switch (buf[10]) { - case 'c': - if (op == "string.concat"sv) { return makeStringConcat(s); } - goto parse_error; - case 's': - if (op == "string.const"sv) { return makeStringConst(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'e': { - switch (buf[8]) { - case 'n': { - switch (buf[14]) { - case 'l': - if (op == "string.encode_lossy_utf8_array"sv) { return makeStringEncode(s, StringEncodeLossyUTF8Array); } - goto parse_error; - case 'w': - if (op == "string.encode_wtf16_array"sv) { return makeStringEncode(s, StringEncodeWTF16Array); } - goto parse_error; - default: goto parse_error; - } - } - case 'q': - if (op == "string.eq"sv) { return makeStringEq(s, StringEqEqual); } - goto parse_error; - default: goto parse_error; - } - } - case 'f': - if (op == "string.from_code_point"sv) { return makeStringNew(s, StringNewFromCodePoint); } - goto parse_error; - case 'm': { - switch (buf[15]) { - case 'u': - if (op == "string.measure_utf8"sv) { return makeStringMeasure(s, StringMeasureUTF8); } - goto parse_error; - case 'w': - if (op == "string.measure_wtf16"sv) { return makeStringMeasure(s, StringMeasureWTF16); } - goto parse_error; - default: goto parse_error; - } - } - case 'n': { - switch (buf[11]) { - case 'l': - if (op == "string.new_lossy_utf8_array"sv) { return makeStringNew(s, StringNewLossyUTF8Array); } - goto parse_error; - case 'w': - if (op == "string.new_wtf16_array"sv) { return makeStringNew(s, StringNewWTF16Array); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'v': { - switch (buf[17]) { - case 'g': - if (op == "stringview_wtf16.get_codeunit"sv) { return makeStringWTF16Get(s); } - goto parse_error; - case 'l': - if (op == "stringview_wtf16.length"sv) { return makeStringMeasure(s, StringMeasureWTF16); } - goto parse_error; - case 's': - if (op == "stringview_wtf16.slice"sv) { return makeStringSliceWTF(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'u': { - switch (buf[7]) { - case 'g': { - switch (buf[10]) { - case '\0': - if (op == "struct.get"sv) { return makeStructGet(s); } - goto parse_error; - case '_': { - switch (buf[11]) { - case 's': - if (op == "struct.get_s"sv) { return makeStructGet(s, true); } - goto parse_error; - case 'u': - if (op == "struct.get_u"sv) { return makeStructGet(s, false); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'n': { - switch (buf[10]) { - case '\0': - if (op == "struct.new"sv) { return makeStructNew(s, false); } - goto parse_error; - case '_': - if (op == "struct.new_default"sv) { return makeStructNew(s, true); } - goto parse_error; - default: goto parse_error; - } - } - case 's': - if (op == "struct.set"sv) { return makeStructSet(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'u': - if (op == "suspend"sv) { return makeSuspend(s); } - goto parse_error; - default: goto parse_error; - } - } - case 't': { - switch (buf[1]) { - case 'a': { - switch (buf[6]) { - case 'c': - if (op == "table.copy"sv) { return makeTableCopy(s); } - goto parse_error; - case 'f': - if (op == "table.fill"sv) { return makeTableFill(s); } - goto parse_error; - case 'g': { - switch (buf[7]) { - case 'e': - if (op == "table.get"sv) { return makeTableGet(s); } - goto parse_error; - case 'r': - if (op == "table.grow"sv) { return makeTableGrow(s); } - goto parse_error; - default: goto parse_error; - } - } - case 's': { - switch (buf[7]) { - case 'e': - if (op == "table.set"sv) { return makeTableSet(s); } - goto parse_error; - case 'i': - if (op == "table.size"sv) { return makeTableSize(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'h': { - switch (buf[2]) { - case 'e': - if (op == "then"sv) { return makeThenOrElse(s); } - goto parse_error; - case 'r': { - switch (buf[5]) { - case '\0': - if (op == "throw"sv) { return makeThrow(s); } - goto parse_error; - case '_': - if (op == "throw_ref"sv) { return makeThrowRef(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'r': { - switch (buf[3]) { - case '\0': - if (op == "try"sv) { return makeTry(s); } - goto parse_error; - case '_': - if (op == "try_table"sv) { return makeTryTable(s); } - goto parse_error; - default: goto parse_error; - } - } - case 'u': { - switch (buf[6]) { - case 'd': - if (op == "tuple.drop"sv) { return makeTupleDrop(s); } - goto parse_error; - case 'e': - if (op == "tuple.extract"sv) { return makeTupleExtract(s); } - goto parse_error; - case 'm': - if (op == "tuple.make"sv) { return makeTupleMake(s); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'u': - if (op == "unreachable"sv) { return makeUnreachable(); } - goto parse_error; - case 'v': { - switch (buf[5]) { - case 'a': { - switch (buf[7]) { - case 'd': { - switch (buf[8]) { - case '\0': - if (op == "v128.and"sv) { return makeBinary(s, BinaryOp::AndVec128); } - goto parse_error; - case 'n': - if (op == "v128.andnot"sv) { return makeBinary(s, BinaryOp::AndNotVec128); } - goto parse_error; - default: goto parse_error; - } - } - case 'y': - if (op == "v128.any_true"sv) { return makeUnary(s, UnaryOp::AnyTrueVec128); } - goto parse_error; - default: goto parse_error; - } - } - case 'b': - if (op == "v128.bitselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::Bitselect); } - goto parse_error; - case 'c': - if (op == "v128.const"sv) { return makeConst(s, Type::v128); } - goto parse_error; - case 'l': { - switch (buf[9]) { - case '\0': - if (op == "v128.load"sv) { return makeLoad(s, Type::v128, /*signed=*/false, 16, /*isAtomic=*/false); } - goto parse_error; - case '1': { - switch (buf[11]) { - case '_': { - switch (buf[12]) { - case 'l': - if (op == "v128.load16_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load16LaneVec128, 2); } - goto parse_error; - case 's': - if (op == "v128.load16_splat"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load16SplatVec128, 2); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[14]) { - case 's': - if (op == "v128.load16x4_s"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load16x4SVec128, 8); } - goto parse_error; - case 'u': - if (op == "v128.load16x4_u"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load16x4UVec128, 8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '3': { - switch (buf[11]) { - case '_': { - switch (buf[12]) { - case 'l': - if (op == "v128.load32_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load32LaneVec128, 4); } - goto parse_error; - case 's': - if (op == "v128.load32_splat"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load32SplatVec128, 4); } - goto parse_error; - case 'z': - if (op == "v128.load32_zero"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load32ZeroVec128, 4); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[14]) { - case 's': - if (op == "v128.load32x2_s"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load32x2SVec128, 8); } - goto parse_error; - case 'u': - if (op == "v128.load32x2_u"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load32x2UVec128, 8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case '6': { - switch (buf[12]) { - case 'l': - if (op == "v128.load64_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load64LaneVec128, 8); } - goto parse_error; - case 's': - if (op == "v128.load64_splat"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load64SplatVec128, 8); } - goto parse_error; - case 'z': - if (op == "v128.load64_zero"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load64ZeroVec128, 8); } - goto parse_error; - default: goto parse_error; - } - } - case '8': { - switch (buf[10]) { - case '_': { - switch (buf[11]) { - case 'l': - if (op == "v128.load8_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load8LaneVec128, 1); } - goto parse_error; - case 's': - if (op == "v128.load8_splat"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load8SplatVec128, 1); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': { - switch (buf[13]) { - case 's': - if (op == "v128.load8x8_s"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load8x8SVec128, 8); } - goto parse_error; - case 'u': - if (op == "v128.load8x8_u"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load8x8UVec128, 8); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; - } - } - default: goto parse_error; - } - } - case 'n': - if (op == "v128.not"sv) { return makeUnary(s, UnaryOp::NotVec128); } - goto parse_error; - case 'o': - if (op == "v128.or"sv) { return makeBinary(s, BinaryOp::OrVec128); } - goto parse_error; - case 's': { - switch (buf[10]) { - case '\0': - if (op == "v128.store"sv) { return makeStore(s, Type::v128, 16, /*isAtomic=*/false); } - goto parse_error; - case '1': - if (op == "v128.store16_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store16LaneVec128, 2); } - goto parse_error; - case '3': - if (op == "v128.store32_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store32LaneVec128, 4); } - goto parse_error; - case '6': - if (op == "v128.store64_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store64LaneVec128, 8); } - goto parse_error; - case '8': - if (op == "v128.store8_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store8LaneVec128, 1); } - goto parse_error; - default: goto parse_error; - } - } - case 'x': - if (op == "v128.xor"sv) { return makeBinary(s, BinaryOp::XorVec128); } - goto parse_error; - default: goto parse_error; - } - } - default: goto parse_error; -} -parse_error: - throw ParseException(std::string(op), s.line, s.col); -#endif // INSTRUCTION_PARSER - -#ifdef NEW_INSTRUCTION_PARSER -#undef NEW_INSTRUCTION_PARSER auto op = *keyword; char buf[33] = {}; memcpy(buf, op.data(), op.size()); @@ -8611,6 +5150,5 @@ switch (buf[0]) { } parse_error: return ctx.in.err(pos, "unrecognized instruction"); -#endif // NEW_INSTRUCTION_PARSER // clang-format on diff --git a/src/parser/parsers.h b/src/parser/parsers.h index 5900deb278b..ab990e7b0ac 100644 --- a/src/parser/parsers.h +++ b/src/parser/parsers.h @@ -918,8 +918,6 @@ MaybeResult<> plaininstr(Ctx& ctx, const std::vector& annotations) { return {}; } -#define NEW_INSTRUCTION_PARSER -#define NEW_WAT_PARSER #include } diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp index dc8aecfe0a6..90116f8f3c3 100644 --- a/src/passes/RemoveNonJSOps.cpp +++ b/src/passes/RemoveNonJSOps.cpp @@ -46,7 +46,6 @@ #include "passes/intrinsics-module.h" #include "support/insert_ordered.h" #include "wasm-builder.h" -#include "wasm-s-parser.h" namespace wasm { diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index 73908afb743..d488171fb85 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -34,7 +34,6 @@ #include "wasm-binary.h" #include "wasm-interpreter.h" #include "wasm-io.h" -#include "wasm-s-parser.h" #include "wasm-stack.h" #include "wasm-validator.h" #include "wasm2c-wrapper.h" @@ -221,19 +220,6 @@ int main(int argc, const char* argv[]) { [&outputSourceMapUrl](Options* o, const std::string& argument) { outputSourceMapUrl = argument; }) - .add( - "--deprecated-wat-parser", - "", - "Use the old, deprecated WAT parser. This option will be removed soon!", - WasmOptOption, - Options::Arguments::Zero, - [](Options*, const std::string&) { useNewWATParser = false; }) - .add("--new-wat-parser", - "", - "Use the experimental new WAT parser", - WasmOptOption, - Options::Arguments::Zero, - [](Options*, const std::string&) { useNewWATParser = true; }) .add_positional("INFILE", Options::Arguments::One, [](Options* o, const std::string& argument) { diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index d334d3380d8..c5de531f5a5 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -32,7 +32,6 @@ #include "support/result.h" #include "wasm-binary.h" #include "wasm-interpreter.h" -#include "wasm-s-parser.h" #include "wasm-validator.h" using namespace wasm; diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp index a6de1fabd9d..feba358c483 100644 --- a/src/tools/wasm2js.cpp +++ b/src/tools/wasm2js.cpp @@ -25,7 +25,6 @@ #include "support/colors.h" #include "support/command-line.h" #include "support/file.h" -#include "wasm-s-parser.h" using namespace cashew; using namespace wasm; diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h deleted file mode 100644 index fe2bda1c7d6..00000000000 --- a/src/wasm-s-parser.h +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2015 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. - */ - -// -// Parses WebAssembly code in S-Expression format, as in .wast files -// such as are in the spec test suite. -// - -#ifndef wasm_wasm_s_parser_h -#define wasm_wasm_s_parser_h - -#include "mixed_arena.h" -#include "parsing.h" // for UniqueNameMapper. TODO: move dependency to cpp file? -#include "wasm-builder.h" -#include "wasm.h" - -namespace wasm { - -class SourceLocation { -public: - IString filename; - uint32_t line; - uint32_t column; - SourceLocation(IString filename_, uint32_t line_, uint32_t column_ = 0) - : filename(filename_), line(line_), column(column_) {} -}; - -// -// An element in an S-Expression: a list or a string -// -class Element { - using List = ArenaVector; - - bool isList_ = true; - List list_; - IString str_; - bool dollared_; - bool quoted_; - -public: - Element(MixedArena& allocator) : list_(allocator) {} - - bool isList() const { return isList_; } - bool isStr() const { return !isList_; } - bool dollared() const { return isStr() && dollared_; } - bool quoted() const { return isStr() && quoted_; } - - size_t line = -1; - size_t col = -1; - // original locations at the start/end of the S-Expression list - SourceLocation* startLoc = nullptr; - SourceLocation* endLoc = nullptr; - - // list methods - List& list(); - Element* operator[](unsigned i); - size_t size() { return list().size(); } - List::Iterator begin() { return list().begin(); } - List::Iterator end() { return list().end(); } - - // string methods - IString str() const; - // convert a string to a string - std::string toString() const; - // convert anything to a string - std::string forceString() const; - Element* setString(IString str__, bool dollared__, bool quoted__); - Element* setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_); - - // comparisons - bool operator==(Name name) { return isStr() && str() == name; } - - template bool operator!=(T t) { return !(*this == t); } - - // printing - friend std::ostream& operator<<(std::ostream& o, const Element& e); - void dump(); -}; - -// -// Generic S-Expression parsing into lists -// -class SExpressionParser { - const char* input; - size_t line; - char const* lineStart; - SourceLocation* loc = nullptr; - - MixedArena allocator; - -public: - // Assumes control of and modifies the input. - SExpressionParser(const char* input); - Element* root; - -private: - Element* parse(); - void skipWhitespace(); - void parseDebugLocation(); - Element* parseString(); -}; - -// -// SExpressions => WebAssembly module -// -class SExpressionWasmBuilder { - Module& wasm; - MixedArena& allocator; - IRProfile profile; - - // The main list of types declared in the module - std::vector types; - std::unordered_map typeIndices; - - std::vector functionNames; - std::vector tableNames; - std::vector elemSegmentNames; - std::vector memoryNames; - std::vector dataSegmentNames; - std::vector globalNames; - std::vector tagNames; - int functionCounter = 0; - int globalCounter = 0; - int tagCounter = 0; - int tableCounter = 0; - int elemCounter = 0; - int memoryCounter = 0; - int dataCounter = 0; - // we need to know function return types before we parse their contents - std::map functionTypes; - std::unordered_map debugInfoFileIndices; - - // Maps type indexes to a mapping of field index => name. This is not the same - // as the field names stored on the wasm object, as that maps types after - // their canonicalization. Canonicalization loses information, which means - // that structurally identical types cannot have different names. However, - // while parsing the text format we keep this mapping of type indexes to names - // which does allow reading such content. - std::unordered_map> fieldNames; - -public: - // Assumes control of and modifies the input. - SExpressionWasmBuilder(Module& wasm, Element& module, IRProfile profile); - -private: - void preParseHeapTypes(Element& module); - // pre-parse types and function definitions, so we know function return types - // before parsing their contents - void preParseFunctionType(Element& s); - bool isImport(Element& curr); - void preParseImports(Element& curr); - void preParseMemory(Element& curr); - void parseModuleElement(Element& curr); - - // function parsing state - std::unique_ptr currFunction; - bool brokeToAutoBlock; - - UniqueNameMapper nameMapper; - - int parseIndex(Element& s); - - Name getFunctionName(Element& s); - Name getTableName(Element& s); - Name getElemSegmentName(Element& s); - Name getMemoryName(Element& s); - Name getDataSegmentName(Element& s); - Name getGlobalName(Element& s); - Name getTagName(Element& s); - void parseStart(Element& s) { wasm.addStart(getFunctionName(*s[1])); } - - Name getMemoryNameAtIdx(Index i); - bool isMemory64(Name memoryName); - bool hasMemoryIdx(Element& s, Index defaultSize, Index i); - - // returns the next index in s - size_t parseFunctionNames(Element& s, Name& name, Name& exportName); - void parseFunction(Element& s, bool preParseImport = false); - - Type stringToType(IString str, bool allowError = false, bool prefix = false) { - return stringToType(str.str, allowError, prefix); - } - Type stringToType(std::string_view str, - bool allowError = false, - bool prefix = false); - HeapType stringToHeapType(IString str, bool prefix = false) { - return stringToHeapType(str.str, prefix); - } - HeapType stringToHeapType(std::string_view str, bool prefix = false); - Type elementToType(Element& s); - // TODO: Use std::string_view for this and similar functions. - Type stringToLaneType(const char* str); - bool isType(IString str) { return stringToType(str, true) != Type::none; } - HeapType getFunctionType(Name name, Element& s); - -public: - Expression* parseExpression(Element* s) { return parseExpression(*s); } - Expression* parseExpression(Element& s); - - Module& getModule() { return wasm; } - -private: - Expression* makeExpression(Element& s); - 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* makeMemorySize(Element& s); - Expression* makeMemoryGrow(Element& s); - Index getLocalIndex(Element& s); - Expression* makeLocalGet(Element& s); - Expression* makeLocalTee(Element& s); - Expression* makeLocalSet(Element& s); - Expression* makeGlobalGet(Element& s); - Expression* makeGlobalSet(Element& s); - Expression* makeBlock(Element& s); - Expression* makeThenOrElse(Element& s); - Expression* makeConst(Element& s, Type type); - Expression* - makeLoad(Element& s, Type type, bool signed_, int bytes, bool isAtomic); - Expression* makeStore(Element& s, Type type, int bytes, bool isAtomic); - Expression* - makeAtomicRMW(Element& s, AtomicRMWOp op, Type type, uint8_t bytes); - Expression* makeAtomicCmpxchg(Element& s, Type type, uint8_t bytes); - Expression* makeAtomicWait(Element& s, Type type); - Expression* makeAtomicNotify(Element& s); - Expression* makeAtomicFence(Element& s); - Expression* makeSIMDExtract(Element& s, SIMDExtractOp op, size_t lanes); - Expression* makeSIMDReplace(Element& s, SIMDReplaceOp op, size_t lanes); - Expression* makeSIMDShuffle(Element& s); - Expression* makeSIMDTernary(Element& s, SIMDTernaryOp op); - Expression* makeSIMDShift(Element& s, SIMDShiftOp op); - Expression* makeSIMDLoad(Element& s, SIMDLoadOp op, int bytes); - Expression* - makeSIMDLoadStoreLane(Element& s, SIMDLoadStoreLaneOp op, int bytes); - Expression* makeMemoryInit(Element& s); - Expression* makeDataDrop(Element& s); - Expression* makeMemoryCopy(Element& s); - Expression* makeMemoryFill(Element& s); - Expression* makePop(Element& s); - Expression* makeIf(Element& s); - Expression* makeMaybeBlock(Element& s, size_t i, Type type); - Expression* makeLoop(Element& s); - Expression* makeCall(Element& s, bool isReturn); - Expression* makeCallIndirect(Element& s, bool isReturn); - template void parseOperands(Element& s, Index i, Index j, T& list) { - while (i < j) { - list.push_back(parseExpression(s[i])); - i++; - } - } - template - void parseCallOperands(Element& s, Index i, Index j, T* call) { - parseOperands(s, i, j, call->operands); - } - enum class LabelType { Break, Exception }; - Name getLabel(Element& s, LabelType labelType = LabelType::Break); - Expression* makeBreak(Element& s, bool isConditional); - Expression* makeBreakTable(Element& s); - Expression* makeReturn(Element& s); - Expression* makeRefNull(Element& s); - Expression* makeRefIsNull(Element& s); - Expression* makeRefFunc(Element& s); - Expression* makeRefEq(Element& s); - Expression* makeTableGet(Element& s); - Expression* makeTableSet(Element& s); - Expression* makeTableSize(Element& s); - Expression* makeTableGrow(Element& s); - Expression* makeTableFill(Element& s); - Expression* makeTableCopy(Element& s); - Expression* makeTry(Element& s); - Expression* makeTryTable(Element& s); - Expression* makeThrow(Element& s); - Expression* makeRethrow(Element& s); - Expression* makeThrowRef(Element& s); - Expression* makeTupleMake(Element& s); - Expression* makeTupleExtract(Element& s); - Expression* makeTupleDrop(Element& s); - Expression* makeCallRef(Element& s, bool isReturn); - Expression* makeRefI31(Element& s); - Expression* makeI31Get(Element& s, bool signed_); - Expression* makeRefTest(Element& s); - Expression* makeRefCast(Element& s); - Expression* makeBrOnNull(Element& s, bool onFail = false); - Expression* makeBrOnCast(Element& s, bool onFail = false); - Expression* makeStructNew(Element& s, bool default_); - Index getStructIndex(Element& type, Element& field); - Expression* makeStructGet(Element& s, bool signed_ = false); - Expression* makeStructSet(Element& s); - Expression* makeArrayNew(Element& s, bool default_); - Expression* makeArrayNewData(Element& s); - Expression* makeArrayNewElem(Element& s); - Expression* makeArrayNewFixed(Element& s); - Expression* makeArrayGet(Element& s, bool signed_ = false); - Expression* makeArraySet(Element& s); - Expression* makeArrayLen(Element& s); - Expression* makeArrayCopy(Element& s); - Expression* makeArrayFill(Element& s); - Expression* makeArrayInitData(Element& s); - Expression* makeArrayInitElem(Element& s); - Expression* makeRefAs(Element& s, RefAsOp op); - Expression* makeRefAsNonNull(Element& s); - Expression* makeStringNew(Element& s, StringNewOp op); - Expression* makeStringConst(Element& s); - Expression* makeStringMeasure(Element& s, StringMeasureOp op); - Expression* makeStringEncode(Element& s, StringEncodeOp op); - Expression* makeStringConcat(Element& s); - Expression* makeStringEq(Element& s, StringEqOp op); - Expression* makeStringWTF8Advance(Element& s); - Expression* makeStringWTF16Get(Element& s); - Expression* makeStringSliceWTF(Element& s); - Expression* makeContBind(Element& s); - Expression* makeContNew(Element& s); - Expression* makeResume(Element& s); - Expression* makeSuspend(Element& s); - - Expression* ignore(Element& s) { WASM_UNREACHABLE("unsupported"); } - - // Helper functions - Type parseBlockType(Element& s, Index& i); - Index parseMemoryLimits(Element& s, Index i, std::unique_ptr& memory); - Index parseMemoryIndex(Element& s, Index i, std::unique_ptr& memory); - Index parseMemoryForInstruction(const std::string& instrName, - Memory& memory, - Element& s, - Index i); - std::vector parseParamOrLocal(Element& s); - std::vector parseParamOrLocal(Element& s, size_t& localIndex); - std::vector parseResults(Element& s); - HeapType parseTypeRef(Element& s); - size_t parseTypeUse(Element& s, - size_t startPos, - HeapType& functionType, - std::vector& namedParams); - size_t parseTypeUse(Element& s, size_t startPos, HeapType& functionType); - - void - stringToBinary(Element& s, std::string_view str, std::vector& data); - void parseMemory(Element& s, bool preParseImport = false); - void parseData(Element& s); - void parseInnerData(Element& s, Index i, std::unique_ptr& seg); - void parseExport(Element& s); - void parseImport(Element& s); - void parseGlobal(Element& s, bool preParseImport = false); - void parseTable(Element& s, bool preParseImport = false); - void parseElem(Element& s, Table* table = nullptr); - ElementSegment* parseElemFinish(Element& s, - std::unique_ptr& segment, - Index i = 1, - bool usesExpressions = false); - - // Parses something like (func ..), (array ..), (struct) - HeapType parseHeapType(Element& s); - - void parseTag(Element& s, bool preParseImport = false); - - Function::DebugLocation getDebugLocation(const SourceLocation& loc); - - // Struct/Array instructions have an unnecessary heap type that is just for - // validation (except for the case of unreachability, but that's not a problem - // anyhow, we can ignore it there). That is, we also have a reference typed - // child from which we can infer the type anyhow, and we just need to check - // that type is the same. - void - validateHeapTypeUsingChild(Expression* child, HeapType heapType, Element& s); -}; - -} // namespace wasm - -#endif // wasm_wasm_s_parser_h diff --git a/src/wasm/CMakeLists.txt b/src/wasm/CMakeLists.txt index e01be3b6a79..16b6d8aed2a 100644 --- a/src/wasm/CMakeLists.txt +++ b/src/wasm/CMakeLists.txt @@ -9,7 +9,6 @@ set(wasm_SOURCES wasm-interpreter.cpp wasm-io.cpp wasm-ir-builder.cpp - wasm-s-parser.cpp wasm-stack.cpp wasm-stack-opts.cpp wasm-type.cpp diff --git a/src/wasm/wasm-io.cpp b/src/wasm/wasm-io.cpp index 10b84bb4dd0..149216e1a83 100644 --- a/src/wasm/wasm-io.cpp +++ b/src/wasm/wasm-io.cpp @@ -29,24 +29,15 @@ #include "support/debug.h" #include "support/path.h" #include "wasm-binary.h" -#include "wasm-s-parser.h" namespace wasm { -bool useNewWATParser = true; - #define DEBUG_TYPE "writer" static void readTextData(std::string& input, Module& wasm, IRProfile profile) { - if (useNewWATParser) { - if (auto parsed = WATParser::parseModule(wasm, input); - auto err = parsed.getErr()) { - Fatal() << err->msg; - } - } else { - SExpressionParser parser(const_cast(input.c_str())); - Element& root = *parser.root; - SExpressionWasmBuilder builder(wasm, *root[0], profile); + if (auto parsed = WATParser::parseModule(wasm, input); + auto err = parsed.getErr()) { + Fatal() << err->msg; } } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp deleted file mode 100644 index f9eae14b832..00000000000 --- a/src/wasm/wasm-s-parser.cpp +++ /dev/null @@ -1,4124 +0,0 @@ -/* - * Copyright 2015 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. - */ - -#include "wasm-s-parser.h" - -#include -#include -#include - -#include "ir/branch-utils.h" -#include "ir/table-utils.h" -#include "shared-constants.h" -#include "support/string.h" -#include "wasm-binary.h" -#include "wasm-builder.h" - -using namespace std::string_literals; - -#define abort_on(str) \ - { throw ParseException(std::string("abort_on ") + str); } -#define element_assert(condition) \ - assert((condition) ? true : (std::cerr << "on: " << *this << '\n' && 0)); - -namespace { -int unhex(char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } - if (c >= 'a' && c <= 'f') { - return c - 'a' + 10; - } - if (c >= 'A' && c <= 'F') { - return c - 'A' + 10; - } - throw wasm::ParseException("invalid hexadecimal"); -} -} // namespace - -namespace wasm { - -// Similar to ParseException but built from an Element. -struct SParseException : public ParseException { - // Receive an element and report its contents, line and column. - SParseException(std::string text, const Element& s) - : ParseException(text + ": " + s.forceString(), s.line, s.col) {} - - // Receive a parent and child element. We print out the full parent for - // context, but report the child line and column inside it. - SParseException(std::string text, const Element& parent, const Element& child) - : ParseException( - text + ": " + parent.forceString(), child.line, child.col) {} -}; - -static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), REC("rec"), - I8("i8"), I16("i16"), DECLARE("declare"), ITEM("item"), OFFSET("offset"), - SUB("sub"), FINAL("final"); - -static Address getAddress(const Element* s) { - return std::stoll(s->toString()); -} - -static void -checkAddress(Address a, const char* errorText, const Element* errorElem) { - if (a > std::numeric_limits::max()) { - throw SParseException(errorText, *errorElem); - } -} - -static bool elementStartsWith(Element& s, IString str) { - return s.isList() && s.size() > 0 && s[0]->isStr() && s[0]->str() == str; -} - -static bool elementStartsWith(Element* s, IString str) { - return elementStartsWith(*s, str); -} - -Element::List& Element::list() { - if (!isList()) { - throw SParseException("expected list", *this); - } - return list_; -} - -Element* Element::operator[](unsigned i) { - if (!isList()) { - throw SParseException("expected list", *this); - } - if (i >= list().size()) { - throw SParseException("expected more elements in list", *this); - } - return list()[i]; -} - -IString Element::str() const { - if (!isStr()) { - throw SParseException("expected string", *this); - } - return str_; -} - -std::string Element::toString() const { - if (!isStr()) { - throw SParseException("expected string", *this); - } - return str_.toString(); -} - -std::string Element::forceString() const { - std::stringstream ss; - ss << *this; - // Limit the size to something reasonable for printing out. - return ss.str().substr(0, 80); -} - -Element* Element::setString(IString str__, bool dollared__, bool quoted__) { - isList_ = false; - str_ = str__; - dollared_ = dollared__; - quoted_ = quoted__; - return this; -} - -Element* -Element::setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_) { - line = line_; - col = col_; - startLoc = startLoc_; - return this; -} - -std::ostream& operator<<(std::ostream& o, const Element& e) { - if (e.isList_) { - o << '('; - for (auto item : e.list_) { - o << ' ' << *item; - } - o << " )"; - } else { - if (e.dollared()) { - o << '$'; - } - o << e.str_.str; - } - return o; -} - -void Element::dump() { - std::cout << "dumping " << this << " : " << *this << ".\n"; -} - -SExpressionParser::SExpressionParser(char const* input) : input(input) { - root = nullptr; - line = 1; - lineStart = input; - while (!root) { // keep parsing until we pass an initial comment - root = parse(); - } -} - -Element* SExpressionParser::parse() { - std::vector stack; - std::vector stackLocs; - Element* curr = allocator.alloc(); - while (1) { - skipWhitespace(); - if (input[0] == 0) { - break; - } - if (input[0] == '(') { - input++; - stack.push_back(curr); - curr = allocator.alloc()->setMetadata( - line, input - lineStart - 1, loc); - stackLocs.push_back(loc); - assert(stack.size() == stackLocs.size()); - } else if (input[0] == ')') { - input++; - curr->endLoc = loc; - auto last = curr; - if (stack.empty()) { - throw ParseException("s-expr stack empty"); - } - curr = stack.back(); - assert(stack.size() == stackLocs.size()); - stack.pop_back(); - loc = stackLocs.back(); - stackLocs.pop_back(); - curr->list().push_back(last); - } else { - curr->list().push_back(parseString()); - } - } - if (stack.size() != 0) { - throw SParseException("stack is not empty", *curr); - } - return curr; -} - -void SExpressionParser::parseDebugLocation() { - // Extracting debug location (if valid) - char const* debugLoc = input + 3; // skipping ";;@" - while (debugLoc[0] && debugLoc[0] == ' ') { - debugLoc++; - } - char const* debugLocEnd = debugLoc; - while (debugLocEnd[0] && debugLocEnd[0] != '\n') { - debugLocEnd++; - } - if (debugLocEnd == debugLoc) { - loc = nullptr; - return; - } - char const* pos = debugLoc; - while (pos < debugLocEnd && pos[0] != ':') { - pos++; - } - if (pos >= debugLocEnd) { - return; // no line number - } - std::string name(debugLoc, pos); - char const* lineStart = ++pos; - while (pos < debugLocEnd && pos[0] != ':') { - pos++; - } - std::string lineStr(lineStart, pos); - if (pos >= debugLocEnd) { - return; // no column number - } - std::string colStr(++pos, debugLocEnd); - void* buf = - allocator.allocSpace(sizeof(SourceLocation), alignof(SourceLocation)); - loc = new (buf) SourceLocation( - IString(name.c_str(), false), atoi(lineStr.c_str()), atoi(colStr.c_str())); -} - -void SExpressionParser::skipWhitespace() { - while (1) { - while (isspace(input[0])) { - if (input[0] == '\n') { - line++; - lineStart = input + 1; - } - input++; - } - if (input[0] == ';' && input[1] == ';') { - if (input[2] == '@') { - parseDebugLocation(); - } - while (input[0] && input[0] != '\n') { - input++; - } - line++; - if (!input[0]) { - return; - } - lineStart = ++input; - } else if (input[0] == '(' && input[1] == ';') { - // Skip nested block comments. - input += 2; - int depth = 1; - while (1) { - if (!input[0]) { - return; - } - if (input[0] == '(' && input[1] == ';') { - input += 2; - depth++; - } else if (input[0] == ';' && input[1] == ')') { - input += 2; - --depth; - if (depth == 0) { - break; - } - } else if (input[0] == '\n') { - line++; - lineStart = input; - input++; - } else { - input++; - } - } - } else { - return; - } - } -} - -Element* SExpressionParser::parseString() { - bool dollared = false; - if (input[0] == '$') { - input++; - dollared = true; - } - char const* start = input; - if (input[0] == '"') { - // parse escaping \", but leave code escaped - we'll handle escaping in - // memory segments specifically - input++; - std::string str; - while (1) { - if (input[0] == 0) { - throw ParseException("unterminated string", line, start - lineStart); - } - if (input[0] == '"') { - break; - } - if (input[0] == '\\') { - str += input[0]; - if (input[1] == 0) { - throw ParseException( - "unterminated string escape", line, start - lineStart); - } - str += input[1]; - input += 2; - continue; - } - str += input[0]; - input++; - } - input++; - return allocator.alloc() - ->setString(IString(str.c_str(), false), dollared, true) - ->setMetadata(line, start - lineStart, loc); - } - while (input[0] && !isspace(input[0]) && input[0] != ')' && input[0] != '(' && - input[0] != ';') { - input++; - } - if (start == input) { - throw ParseException("expected string", line, input - lineStart); - } - - std::string temp; - temp.assign(start, input - start); - - auto ret = allocator.alloc() - ->setString(IString(temp.c_str(), false), dollared, false) - ->setMetadata(line, start - lineStart, loc); - - return ret; -} - -SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm, - Element& module, - IRProfile profile) - : wasm(wasm), allocator(wasm.allocator), profile(profile) { - if (module.size() == 0) { - throw ParseException("empty toplevel, expected module"); - } - if (module[0]->str() != MODULE) { - throw ParseException("toplevel does not start with module"); - } - if (module.size() == 1) { - return; - } - Index i = 1; - if (module[i]->dollared()) { - wasm.name = module[i]->str(); - if (module.size() == 2) { - return; - } - i++; - } - - // spec tests have a `binary` keyword after the optional module name. Skip it - Name BINARY("binary"); - if (module[i]->isStr() && module[i]->str() == BINARY && - !module[i]->quoted()) { - i++; - } - - if (i < module.size() && module[i]->isStr()) { - // these s-expressions contain a binary module, actually - std::vector data; - for (; i < module.size(); ++i) { - stringToBinary(*module[i], module[i]->str().str, data); - } - // TODO: support applying features here - WasmBinaryReader binaryBuilder(wasm, FeatureSet::MVP, data); - binaryBuilder.read(); - return; - } - - preParseHeapTypes(module); - - Index implementedFunctions = 0; - functionCounter = 0; - for (unsigned j = i; j < module.size(); j++) { - auto& s = *module[j]; - preParseFunctionType(s); - preParseImports(s); - preParseMemory(s); - if (elementStartsWith(s, FUNC) && !isImport(s)) { - implementedFunctions++; - } - } - // we go through the functions again, now parsing them, and the counter begins - // from where imports ended - functionCounter -= implementedFunctions; - for (unsigned j = i; j < module.size(); j++) { - parseModuleElement(*module[j]); - } -} - -bool SExpressionWasmBuilder::isImport(Element& curr) { - for (Index i = 0; i < curr.size(); i++) { - auto& x = *curr[i]; - if (elementStartsWith(x, IMPORT)) { - return true; - } - } - return false; -} - -void SExpressionWasmBuilder::preParseImports(Element& curr) { - IString id = curr[0]->str(); - if (id == IMPORT) { - parseImport(curr); - } - if (isImport(curr)) { - if (id == FUNC) { - parseFunction(curr, true /* preParseImport */); - } else if (id == GLOBAL) { - parseGlobal(curr, true /* preParseImport */); - } else if (id == TABLE) { - parseTable(curr, true /* preParseImport */); - } else if (id == MEMORY) { - parseMemory(curr, true /* preParseImport */); - } else if (id == TAG) { - parseTag(curr, true /* preParseImport */); - } else { - throw SParseException("fancy import we don't support yet", curr); - } - } -} - -void SExpressionWasmBuilder::preParseMemory(Element& curr) { - IString id = curr[0]->str(); - if (id == MEMORY && !isImport(curr)) { - parseMemory(curr); - } -} - -void SExpressionWasmBuilder::parseModuleElement(Element& curr) { - if (isImport(curr)) { - return; // already done - } - IString id = curr[0]->str(); - if (id == MEMORY) { - return; // already done - } - if (id == START) { - return parseStart(curr); - } - if (id == FUNC) { - return parseFunction(curr); - } - if (id == DATA) { - return parseData(curr); - } - if (id == EXPORT) { - return parseExport(curr); - } - if (id == IMPORT) { - return; // already done - } - if (id == GLOBAL) { - return parseGlobal(curr); - } - if (id == TABLE) { - return parseTable(curr); - } - if (id == ELEM) { - return parseElem(curr); - } - if (id == TYPE) { - return; // already done - } - if (id == REC) { - return; // already done - } - if (id == TAG) { - return parseTag(curr); - } - std::cerr << "bad module element " << id.str << '\n'; - throw SParseException("unknown module element", curr); -} - -int SExpressionWasmBuilder::parseIndex(Element& s) { - try { - return std::stoi(s.toString()); - } catch (...) { - throw SParseException("expected integer", s); - } -} - -Name SExpressionWasmBuilder::getFunctionName(Element& s) { - if (s.dollared()) { - return s.str(); - } else { - // index - size_t offset = parseIndex(s); - if (offset >= functionNames.size()) { - throw SParseException("unknown function in getFunctionName", s); - } - return functionNames[offset]; - } -} - -Name SExpressionWasmBuilder::getTableName(Element& s) { - if (s.dollared()) { - return s.str(); - } else { - // index - size_t offset = parseIndex(s); - if (offset >= tableNames.size()) { - throw SParseException("unknown table in getTableName", s); - } - return tableNames[offset]; - } -} - -Name SExpressionWasmBuilder::getElemSegmentName(Element& s) { - if (s.dollared()) { - return s.str(); - } else { - // index - size_t offset = parseIndex(s); - if (offset >= elemSegmentNames.size()) { - throw SParseException("unknown elem segment", s); - } - return elemSegmentNames[offset]; - } -} - -bool SExpressionWasmBuilder::isMemory64(Name memoryName) { - auto* memory = wasm.getMemoryOrNull(memoryName); - if (!memory) { - throw ParseException("invalid memory name in isMemory64: "s + - memoryName.toString()); - } - return memory->is64(); -} - -Name SExpressionWasmBuilder::getMemoryNameAtIdx(Index i) { - if (i >= memoryNames.size()) { - throw ParseException("unknown memory in getMemoryName: "s + - std::to_string(i)); - } - return memoryNames[i]; -} - -Name SExpressionWasmBuilder::getMemoryName(Element& s) { - if (s.dollared()) { - return s.str(); - } else { - // index - size_t offset = parseIndex(s); - return getMemoryNameAtIdx(offset); - } -} - -Name SExpressionWasmBuilder::getDataSegmentName(Element& s) { - if (s.dollared()) { - return s.str(); - } else { - // index - size_t offset = parseIndex(s); - if (offset >= dataSegmentNames.size()) { - throw SParseException("unknown data segment", s); - } - return dataSegmentNames[offset]; - } -} - -Name SExpressionWasmBuilder::getGlobalName(Element& s) { - if (s.dollared()) { - return s.str(); - } else { - // index - size_t offset = parseIndex(s); - if (offset >= globalNames.size()) { - throw SParseException("unknown global in getGlobalName", s); - } - return globalNames[offset]; - } -} - -Name SExpressionWasmBuilder::getTagName(Element& s) { - if (s.dollared()) { - return s.str(); - } else { - // index - size_t offset = parseIndex(s); - if (offset >= tagNames.size()) { - throw SParseException("unknown tag in getTagName", s); - } - return tagNames[offset]; - } -} - -// Parse various forms of (param ...) or (local ...) element. This ignores all -// parameter or local names when specified. -std::vector SExpressionWasmBuilder::parseParamOrLocal(Element& s) { - size_t fakeIndex = 0; - std::vector namedParams = parseParamOrLocal(s, fakeIndex); - std::vector params; - for (auto& p : namedParams) { - params.push_back(p.type); - } - return params; -} - -// Parses various forms of (param ...) or (local ...) element: -// (param $name type) (e.g. (param $a i32)) -// (param type+) (e.g. (param i32 f64)) -// (local $name type) (e.g. (local $a i32)) -// (local type+) (e.g. (local i32 f64)) -// If the name is unspecified, it will create one using localIndex. -std::vector -SExpressionWasmBuilder::parseParamOrLocal(Element& s, size_t& localIndex) { - assert(elementStartsWith(s, PARAM) || elementStartsWith(s, LOCAL)); - std::vector namedParams; - if (s.size() == 1) { // (param) or (local) - return namedParams; - } - - for (size_t i = 1; i < s.size(); i++) { - IString name; - if (s[i]->dollared()) { - if (i != 1) { - throw SParseException("invalid wasm type", *s[i]); - } - if (i + 1 >= s.size()) { - throw SParseException("invalid param entry", s); - } - name = s[i]->str(); - i++; - } else { - name = Name::fromInt(localIndex); - } - localIndex++; - Type type; - type = elementToType(*s[i]); - if (elementStartsWith(s, PARAM) && type.isTuple()) { - throw SParseException("params may not have tuple types", *s[i]); - } - namedParams.emplace_back(name, type); - } - return namedParams; -} - -// Parses (result type) element. (e.g. (result i32)) -std::vector SExpressionWasmBuilder::parseResults(Element& s) { - assert(elementStartsWith(s, RESULT)); - std::vector types; - for (size_t i = 1; i < s.size(); i++) { - types.push_back(elementToType(*s[i])); - } - return types; -} - -// Parses an element that references an entry in the type section. The element -// should be in the form of (type name) or (type index). -// (e.g. (type $a), (type 0)) -HeapType SExpressionWasmBuilder::parseTypeRef(Element& s) { - assert(elementStartsWith(s, TYPE)); - if (s.size() != 2) { - throw SParseException("invalid type reference", s); - } - auto heapType = parseHeapType(*s[1]); - if (!heapType.isSignature()) { - throw SParseException("expected signature type", s); - } - return heapType; -} - -// Parses typeuse, a reference to a type definition. It is in the form of either -// (type index) or (type name), possibly augmented by inlined (param) and -// (result) nodes. (type) node can be omitted as well. Outputs are returned by -// parameter references. -// typeuse ::= (type index|name)+ | -// (type index|name)+ (param ..)* (result ..)* | -// (param ..)* (result ..)* -size_t -SExpressionWasmBuilder::parseTypeUse(Element& s, - size_t startPos, - HeapType& functionType, - std::vector& namedParams) { - std::vector params, results; - size_t i = startPos; - - bool typeExists = false, paramsOrResultsExist = false; - if (i < s.size() && elementStartsWith(*s[i], TYPE)) { - typeExists = true; - functionType = parseTypeRef(*s[i++]); - } - - size_t paramPos = i; - size_t localIndex = 0; - - while (i < s.size() && elementStartsWith(*s[i], PARAM)) { - paramsOrResultsExist = true; - auto newParams = parseParamOrLocal(*s[i++], localIndex); - namedParams.insert(namedParams.end(), newParams.begin(), newParams.end()); - for (auto p : newParams) { - params.push_back(p.type); - } - } - - while (i < s.size() && elementStartsWith(*s[i], RESULT)) { - paramsOrResultsExist = true; - auto newResults = parseResults(*s[i++]); - results.insert(results.end(), newResults.begin(), newResults.end()); - } - - auto inlineSig = Signature(Type(params), Type(results)); - - // If none of type/param/result exists, this is equivalent to a type that does - // not have parameters and returns nothing. - if (!typeExists && !paramsOrResultsExist) { - paramsOrResultsExist = true; - } - - if (!typeExists) { - functionType = inlineSig; - } else if (paramsOrResultsExist) { - // verify that (type) and (params)/(result) match - if (inlineSig != functionType.getSignature()) { - throw SParseException("type and param/result don't match", *s[paramPos]); - } - } - - // Add implicitly defined type to global list so it has an index - if (std::find(types.begin(), types.end(), functionType) == types.end()) { - types.push_back(functionType); - } - - // If only (type) is specified, populate `namedParams` - if (!paramsOrResultsExist) { - size_t index = 0; - assert(functionType.isSignature()); - Signature sig = functionType.getSignature(); - for (const auto& param : sig.params) { - namedParams.emplace_back(Name::fromInt(index++), param); - } - } - - return i; -} - -// Parses a typeuse. Use this when only FunctionType* is needed. -size_t SExpressionWasmBuilder::parseTypeUse(Element& s, - size_t startPos, - HeapType& functionType) { - std::vector params; - return parseTypeUse(s, startPos, functionType, params); -} - -void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { - // Iterate through each individual type definition, calling `f` with the - // definition and its recursion group number. - auto forEachType = [&](auto f) { - size_t groupNumber = 0; - for (auto* elemPtr : module) { - auto& elem = *elemPtr; - if (elementStartsWith(elem, TYPE)) { - f(elem, groupNumber++); - } else if (elementStartsWith(elem, REC)) { - for (auto* innerPtr : elem) { - auto& inner = *innerPtr; - if (elementStartsWith(inner, TYPE)) { - f(inner, groupNumber); - } - } - ++groupNumber; - } - } - }; - - // Map type names to indices - size_t numTypes = 0; - forEachType([&](Element& elem, size_t) { - if (elem[1]->dollared()) { - std::string name = elem[1]->toString(); - if (!typeIndices.insert({name, numTypes}).second) { - throw SParseException("duplicate function type", elem); - } - } - ++numTypes; - }); - - TypeBuilder builder(numTypes); - - // Create recursion groups - size_t currGroup = 0, groupStart = 0, groupLength = 0; - auto finishGroup = [&]() { - builder.createRecGroup(groupStart, groupLength); - groupStart = groupStart + groupLength; - groupLength = 0; - }; - forEachType([&](Element&, size_t group) { - if (group != currGroup) { - finishGroup(); - currGroup = group; - } - ++groupLength; - }); - finishGroup(); - - auto parseHeapType = [&](Element& elem) -> HeapType { - auto name = elem.toString(); - if (elem.dollared()) { - auto it = typeIndices.find(name); - if (it == typeIndices.end()) { - throw SParseException("invalid type name", elem); - } else { - return builder[it->second]; - } - } else if (String::isNumber(name)) { - size_t index = parseIndex(elem); - if (index >= numTypes) { - throw SParseException("invalid type index", elem); - } - return builder[index]; - } else { - return stringToHeapType(elem.str()); - } - }; - - auto parseRefType = [&](Element& elem) -> Type { - // '(' 'ref' 'null'? ht ')' - auto nullable = - elem[1]->isStr() && *elem[1] == NULL_ ? Nullable : NonNullable; - auto& referent = nullable ? *elem[2] : *elem[1]; - auto ht = parseHeapType(referent); - if (ht.isBasic()) { - return Type(ht, nullable); - } else { - return builder.getTempRefType(ht, nullable); - } - }; - - auto parseValType = [&](Element& elem) { - if (elem.isStr()) { - return stringToType(elem.str()); - } else if (*elem[0] == REF) { - return parseRefType(elem); - } else { - throw SParseException("unknown valtype kind", elem); - } - }; - - auto parseParams = [&](Element& elem) { - auto it = ++elem.begin(); - if (it != elem.end() && (*it)->dollared()) { - ++it; - } - std::vector params; - for (auto end = elem.end(); it != end; ++it) { - params.push_back(parseValType(**it)); - } - return params; - }; - - auto parseResults = [&](Element& elem) { - std::vector results; - for (auto it = ++elem.begin(); it != elem.end(); ++it) { - results.push_back(parseValType(**it)); - } - return results; - }; - - auto parseSignatureDef = [&](Element& elem, bool nominal) { - // '(' 'func' vec(param) vec(result) ')' - // param ::= '(' 'param' id? valtype ')' - // result ::= '(' 'result' valtype ')' - std::vector params, results; - auto end = elem.end() - (nominal ? 1 : 0); - for (auto it = ++elem.begin(); it != end; ++it) { - Element& curr = **it; - if (elementStartsWith(curr, PARAM)) { - auto newParams = parseParams(curr); - params.insert(params.end(), newParams.begin(), newParams.end()); - } else if (elementStartsWith(curr, RESULT)) { - auto newResults = parseResults(curr); - results.insert(results.end(), newResults.begin(), newResults.end()); - } - } - return Signature(builder.getTempTupleType(params), - builder.getTempTupleType(results)); - }; - - auto parseContinuationDef = [&](Element& elem) { - // '(' 'cont' index ')' | '(' 'cont' name ')' - HeapType ft = parseHeapType(*elem[1]); - if (!ft.isSignature()) { - throw ParseException( - "cont type must be created from func type", elem.line, elem.col); - } - return Continuation(ft); - }; - - // Parses a field, and notes the name if one is found. - auto parseField = [&](Element* elem, Name& name) { - Mutability mutable_ = Immutable; - // elem is a list, containing either - // TYPE - // or - // (field TYPE) - // or - // (field $name TYPE) - if (elementStartsWith(elem, FIELD)) { - if (elem->size() == 3) { - name = (*elem)[1]->str(); - } - elem = (*elem)[elem->size() - 1]; - } - // The element may also be (mut (..)). - if (elementStartsWith(elem, MUT)) { - mutable_ = Mutable; - elem = (*elem)[1]; - } - if (elem->isStr()) { - // elem is a simple string name like "i32". It can be a normal wasm - // type, or one of the special types only available in fields. - if (*elem == I8) { - return Field(Field::i8, mutable_); - } else if (*elem == I16) { - return Field(Field::i16, mutable_); - } - } - // Otherwise it's an arbitrary type. - return Field(parseValType(*elem), mutable_); - }; - - auto parseStructDef = [&](Element& elem, size_t typeIndex, bool nominal) { - FieldList fields; - Index end = elem.size() - (nominal ? 1 : 0); - for (Index i = 1; i < end; i++) { - Name name; - fields.emplace_back(parseField(elem[i], name)); - if (name.is()) { - // Only add the name to the map if it exists. - fieldNames[typeIndex][i - 1] = name; - } - } - return Struct(fields); - }; - - auto parseArrayDef = [&](Element& elem) { - Name unused; - return Array(parseField(elem[1], unused)); - }; - - size_t index = 0; - forEachType([&](Element& elem, size_t) { - Element& def = elem[1]->dollared() ? *elem[2] : *elem[1]; - Element& kind = *def[0]; - Element* super = nullptr; - if (kind == SUB) { - Index i = 1; - if (*def[i] == FINAL) { - ++i; - } else { - builder[index].setOpen(); - } - if (def[i]->dollared()) { - super = def[i]; - ++i; - } - Element& subtype = *def[i++]; - if (i != def.size()) { - throw SParseException("invalid 'sub' form", kind); - } - if (!subtype.isList() || subtype.size() < 1) { - throw SParseException("invalid subtype definition", subtype); - } - Element& subtypeKind = *subtype[0]; - if (subtypeKind == FUNC) { - builder[index] = parseSignatureDef(subtype, 0); - } else if (kind == CONT) { - builder[index] = parseContinuationDef(subtype); - } else if (subtypeKind == STRUCT) { - builder[index] = parseStructDef(subtype, index, 0); - } else if (subtypeKind == ARRAY) { - builder[index] = parseArrayDef(subtype); - } else { - throw SParseException("unknown subtype kind", subtypeKind); - } - } else { - if (kind == FUNC) { - builder[index] = parseSignatureDef(def, 0); - } else if (kind == CONT) { - builder[index] = parseContinuationDef(def); - } else if (kind == STRUCT) { - builder[index] = parseStructDef(def, index, 0); - } else if (kind == ARRAY) { - builder[index] = parseArrayDef(def); - } else { - throw SParseException("unknown heaptype kind", kind); - } - } - if (super) { - auto it = typeIndices.find(super->toString()); - if (!super->dollared() || it == typeIndices.end()) { - throw SParseException("unknown supertype", elem, *super); - } - builder[index].subTypeOf(builder[it->second]); - } - ++index; - }); - - auto result = builder.build(); - if (auto* err = result.getError()) { - // Find the name to provide a better error message. - std::stringstream msg; - msg << "Invalid type: " << err->reason; - for (auto& [name, index] : typeIndices) { - if (index == err->index) { - Fatal() << msg.str() << " at type $" << name; - } - } - // No name, just report the index. - Fatal() << msg.str() << " at index " << err->index; - } - types = *result; - - for (auto& [name, index] : typeIndices) { - auto type = types[index]; - // A type may appear in the type section more than once, but we canonicalize - // types internally, so there will be a single name chosen for that type. Do - // so determistically. - if (wasm.typeNames.count(type) && wasm.typeNames[type].name.str < name) { - continue; - } - auto& currTypeNames = wasm.typeNames[type]; - currTypeNames.name = name; - if (type.isStruct()) { - currTypeNames.fieldNames = fieldNames[index]; - } - } -} - -void SExpressionWasmBuilder::preParseFunctionType(Element& s) { - IString id = s[0]->str(); - if (id != FUNC) { - return; - } - size_t i = 1; - Name name, exportName; - i = parseFunctionNames(s, name, exportName); - if (!name.is()) { - // unnamed, use an index - name = Name::fromInt(functionCounter); - } - functionNames.push_back(name); - functionCounter++; - parseTypeUse(s, i, functionTypes[name]); -} - -size_t SExpressionWasmBuilder::parseFunctionNames(Element& s, - Name& name, - Name& exportName) { - size_t i = 1; - while (i < s.size() && i < 3 && s[i]->isStr()) { - if (s[i]->dollared()) { - name = s[i]->str(); - i++; - } else { - break; - } - } - if (i < s.size() && s[i]->isList()) { - auto& inner = *s[i]; - if (elementStartsWith(inner, EXPORT)) { - exportName = inner[1]->str(); - i++; - } - } -#if 0 - if (exportName.is() && !name.is()) { - name = exportName; // useful for debugging - } -#endif - return i; -} - -void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { - brokeToAutoBlock = false; - - Name name, exportName; - size_t i = parseFunctionNames(s, name, exportName); - bool hasExplicitName = name.is(); - if (!preParseImport) { - if (!name.is()) { - // unnamed, use an index - name = Name::fromInt(functionCounter); - } - functionCounter++; - } else { - // just preparsing, functionCounter was incremented by preParseFunctionType - if (!name.is()) { - // unnamed, use an index - name = functionNames[functionCounter - 1]; - } - } - if (exportName.is()) { - auto ex = std::make_unique(); - ex->name = exportName; - ex->value = name; - ex->kind = ExternalKind::Function; - if (wasm.getExportOrNull(ex->name)) { - throw SParseException("duplicate export", s); - } - wasm.addExport(ex.release()); - } - - // parse import - Name importModule, importBase; - if (i < s.size() && elementStartsWith(*s[i], IMPORT)) { - Element& curr = *s[i]; - importModule = curr[1]->str(); - importBase = curr[2]->str(); - i++; - } - - // parse typeuse: type/param/result - HeapType type; - std::vector params; - i = parseTypeUse(s, i, type, params); - - // when (import) is inside a (func) element, this is not a function definition - // but an import. - if (importModule.is()) { - if (!importBase.size()) { - throw SParseException("module but no base for import", s); - } - if (!preParseImport) { - throw SParseException("!preParseImport in func", s); - } - auto im = std::make_unique(); - im->setName(name, hasExplicitName); - im->module = importModule; - im->base = importBase; - im->type = type; - functionTypes[name] = type; - if (wasm.getFunctionOrNull(im->name)) { - throw SParseException("duplicate import", s); - } - wasm.addFunction(std::move(im)); - if (currFunction) { - throw SParseException("import module inside function dec", s); - } - nameMapper.clear(); - return; - } - // at this point this not an import but a real function definition. - if (preParseImport) { - throw SParseException("preParseImport in func", s); - } - - size_t localIndex = params.size(); // local index for params and locals - - // parse locals - std::vector vars; - while (i < s.size() && elementStartsWith(*s[i], LOCAL)) { - auto newVars = parseParamOrLocal(*s[i++], localIndex); - vars.insert(vars.end(), newVars.begin(), newVars.end()); - } - - // make a new function - currFunction = std::unique_ptr( - Builder(wasm).makeFunction(name, std::move(params), type, std::move(vars))); - currFunction->hasExplicitName = hasExplicitName; - currFunction->profile = profile; - - // parse body - Block* autoBlock = nullptr; // may need to add a block for the very top level - auto ensureAutoBlock = [&]() { - if (!autoBlock) { - autoBlock = allocator.alloc(); - autoBlock->list.push_back(currFunction->body); - currFunction->body = autoBlock; - } - }; - while (i < s.size()) { - Expression* ex = parseExpression(*s[i++]); - if (!currFunction->body) { - currFunction->body = ex; - } else { - ensureAutoBlock(); - autoBlock->list.push_back(ex); - } - } - - if (brokeToAutoBlock) { - ensureAutoBlock(); - autoBlock->name = FAKE_RETURN; - } - if (autoBlock) { - autoBlock->finalize(type.getSignature().results); - } - if (!currFunction->body) { - currFunction->body = allocator.alloc(); - } - if (s.startLoc) { - currFunction->prologLocation.insert(getDebugLocation(*s.startLoc)); - } - if (s.endLoc) { - currFunction->epilogLocation.insert(getDebugLocation(*s.endLoc)); - } - if (wasm.getFunctionOrNull(currFunction->name)) { - throw SParseException("duplicate function", s); - } - wasm.addFunction(currFunction.release()); - nameMapper.clear(); -} - -Type SExpressionWasmBuilder::stringToType(std::string_view str, - bool allowError, - bool prefix) { - if (str.size() >= 3) { - if (str[0] == 'i') { - if (str[1] == '3' && str[2] == '2' && (prefix || str.size() == 3)) { - return Type::i32; - } - if (str[1] == '6' && str[2] == '4' && (prefix || str.size() == 3)) { - return Type::i64; - } - } - if (str[0] == 'f') { - if (str[1] == '3' && str[2] == '2' && (prefix || str.size() == 3)) { - return Type::f32; - } - if (str[1] == '6' && str[2] == '4' && (prefix || str.size() == 3)) { - return Type::f64; - } - } - } - if (str.size() >= 4) { - if (str[0] == 'v') { - if (str[1] == '1' && str[2] == '2' && str[3] == '8' && - (prefix || str.size() == 4)) { - return Type::v128; - } - } - } - if (str.substr(0, 7) == "funcref" && (prefix || str.size() == 7)) { - return Type(HeapType::func, Nullable); - } - if (str.substr(0, 7) == "contref" && (prefix || str.size() == 7)) { - return Type(HeapType::cont, Nullable); - } - if (str.substr(0, 9) == "externref" && (prefix || str.size() == 9)) { - return Type(HeapType::ext, Nullable); - } - if (str.substr(0, 6) == "anyref" && (prefix || str.size() == 6)) { - return Type(HeapType::any, Nullable); - } - if (str.substr(0, 5) == "eqref" && (prefix || str.size() == 5)) { - return Type(HeapType::eq, Nullable); - } - if (str.substr(0, 6) == "i31ref" && (prefix || str.size() == 6)) { - return Type(HeapType::i31, Nullable); - } - if (str.substr(0, 9) == "structref" && (prefix || str.size() == 9)) { - return Type(HeapType::struct_, Nullable); - } - if (str.substr(0, 8) == "arrayref" && (prefix || str.size() == 8)) { - return Type(HeapType::array, Nullable); - } - if (str.substr(0, 6) == "exnref" && (prefix || str.size() == 6)) { - return Type(HeapType::exn, Nullable); - } - if (str.substr(0, 9) == "stringref" && (prefix || str.size() == 9)) { - return Type(HeapType::string, Nullable); - } - if (str.substr(0, 7) == "nullref" && (prefix || str.size() == 7)) { - return Type(HeapType::none, Nullable); - } - if (str.substr(0, 13) == "nullexternref" && (prefix || str.size() == 13)) { - return Type(HeapType::noext, Nullable); - } - if (str.substr(0, 11) == "nullfuncref" && (prefix || str.size() == 11)) { - return Type(HeapType::nofunc, Nullable); - } - if (str.substr(0, 10) == "nullexnref" && (prefix || str.size() == 10)) { - return Type(HeapType::noexn, Nullable); - } - if (str.substr(0, 11) == "nullcontref" && (prefix || str.size() == 11)) { - return Type(HeapType::nocont, Nullable); - } - if (allowError) { - return Type::none; - } - throw ParseException(std::string("invalid wasm type: ") + - std::string(str.data(), str.size())); -} - -HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str, - bool prefix) { - if (str.substr(0, 4) == "func" && (prefix || str.size() == 4)) { - return HeapType::func; - } - if (str.substr(0, 4) == "cont" && (prefix || str.size() == 4)) { - return HeapType::cont; - } - if (str.substr(0, 2) == "eq" && (prefix || str.size() == 2)) { - return HeapType::eq; - } - if (str.substr(0, 6) == "extern" && (prefix || str.size() == 6)) { - return HeapType::ext; - } - if (str.substr(0, 3) == "any" && (prefix || str.size() == 3)) { - return HeapType::any; - } - if (str.substr(0, 3) == "i31" && (prefix || str.size() == 3)) { - return HeapType::i31; - } - if (str.substr(0, 6) == "struct" && (prefix || str.size() == 6)) { - return HeapType::struct_; - } - if (str.substr(0, 5) == "array" && (prefix || str.size() == 5)) { - return HeapType::array; - } - if (str.substr(0, 3) == "exn" && (prefix || str.size() == 3)) { - return HeapType::exn; - } - if (str.substr(0, 6) == "string" && (prefix || str.size() == 6)) { - return HeapType::string; - } - if (str.substr(0, 4) == "none" && (prefix || str.size() == 4)) { - return HeapType::none; - } - if (str.substr(0, 8) == "noextern" && (prefix || str.size() == 8)) { - return HeapType::noext; - } - if (str.substr(0, 6) == "nofunc" && (prefix || str.size() == 6)) { - return HeapType::nofunc; - } - if (str.substr(0, 6) == "nofunc" && (prefix || str.size() == 6)) { - return HeapType::nofunc; - } - if (str.substr(0, 5) == "noexn" && (prefix || str.size() == 5)) { - return HeapType::noexn; - } - if (str.substr(0, 6) == "nocont" && (prefix || str.size() == 6)) { - return HeapType::nocont; - } - throw ParseException(std::string("invalid wasm heap type: ") + - std::string(str.data(), str.size())); -} - -Type SExpressionWasmBuilder::elementToType(Element& s) { - if (s.isStr()) { - return stringToType(s.str()); - } - auto& list = s.list(); - auto size = list.size(); - if (elementStartsWith(s, REF)) { - // It's a reference. It should be in the form - // (ref $name) - // or - // (ref null $name) - // and also $name can be the expanded structure of the type and not a name, - // so something like (ref (func (result i32))), etc. - if (size != 2 && size != 3) { - throw SParseException(std::string("invalid reference type size"), s); - } - if (size == 3 && *list[1] != NULL_) { - throw SParseException(std::string("invalid reference type qualifier"), s); - } - Nullability nullable = NonNullable; - size_t i = 1; - if (size == 3) { - nullable = Nullable; - i++; - } - return Type(parseHeapType(*s[i]), nullable); - } - if (elementStartsWith(s, TUPLE)) { - // It's a tuple. - std::vector types; - for (size_t i = 1; i < s.size(); ++i) { - types.push_back(elementToType(*list[i])); - } - return Type(types); - } - throw SParseException(std::string("expected type, got list"), s); -} - -Type SExpressionWasmBuilder::stringToLaneType(const char* str) { - if (strcmp(str, "i8x16") == 0) { - return Type::i32; - } - if (strcmp(str, "i16x8") == 0) { - return Type::i32; - } - if (strcmp(str, "i32x4") == 0) { - return Type::i32; - } - if (strcmp(str, "i64x2") == 0) { - return Type::i64; - } - if (strcmp(str, "f32x4") == 0) { - return Type::f32; - } - if (strcmp(str, "f64x2") == 0) { - return Type::f64; - } - return Type::none; -} - -HeapType SExpressionWasmBuilder::getFunctionType(Name name, Element& s) { - auto iter = functionTypes.find(name); - if (iter == functionTypes.end()) { - throw SParseException("invalid call target: " + std::string(name.str), s); - } - return iter->second; -} - -Function::DebugLocation -SExpressionWasmBuilder::getDebugLocation(const SourceLocation& loc) { - IString file = loc.filename; - auto& debugInfoFileNames = wasm.debugInfoFileNames; - auto iter = debugInfoFileIndices.find(file); - if (iter == debugInfoFileIndices.end()) { - Index index = debugInfoFileNames.size(); - debugInfoFileNames.push_back(file.toString()); - debugInfoFileIndices[file] = index; - } - uint32_t fileIndex = debugInfoFileIndices[file]; - return {fileIndex, loc.line, loc.column}; -} - -Expression* SExpressionWasmBuilder::parseExpression(Element& s) { - Expression* result = makeExpression(s); - if (s.startLoc && currFunction) { - currFunction->debugLocations[result] = getDebugLocation(*s.startLoc); - } - return result; -} - -Expression* SExpressionWasmBuilder::makeExpression(Element& s){ -#define INSTRUCTION_PARSER -#include "gen-s-parser.inc" -} - -Expression* SExpressionWasmBuilder::makeUnreachable() { - return allocator.alloc(); -} - -Expression* SExpressionWasmBuilder::makeNop() { return allocator.alloc(); } - -Expression* SExpressionWasmBuilder::makeBinary(Element& s, BinaryOp op) { - auto ret = allocator.alloc(); - ret->op = op; - ret->left = parseExpression(s[1]); - ret->right = parseExpression(s[2]); - ret->finalize(); - return ret; -} - -Expression* SExpressionWasmBuilder::makeUnary(Element& s, UnaryOp op) { - auto ret = allocator.alloc(); - ret->op = op; - ret->value = parseExpression(s[1]); - ret->finalize(); - return ret; -} - -Expression* SExpressionWasmBuilder::makeSelect(Element& s) { - auto ret = allocator.alloc