diff options
author | Thomas Lively <tlively@google.com> | 2022-10-11 11:16:14 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-11 16:16:14 +0000 |
commit | b83450ed1fd98cec4453024f57f892b31851ea50 (patch) | |
tree | bf0467d96c9966d0f4699ea0afcdf25905b4098c | |
parent | 6d4ac3162c290e32a98de349d49e26e904a40414 (diff) | |
download | binaryen-b83450ed1fd98cec4453024f57f892b31851ea50.tar.gz binaryen-b83450ed1fd98cec4453024f57f892b31851ea50.tar.bz2 binaryen-b83450ed1fd98cec4453024f57f892b31851ea50.zip |
Make `Name` a pointer, length pair (#5122)
With the goal of supporting null characters (i.e. zero bytes) in strings.
Rewrite the underlying interned `IString` to store a `std::string_view` rather
than a `const char*`, reduce the number of map lookups necessary to intern a
string, and present a more immutable interface.
Most importantly, replace the `c_str()` method that returned a `const char*`
with a `toString()` method that returns a `std::string`. This new method can
correctly handle strings containing null characters. A `const char*` can still
be had by calling `data()` on the `std::string_view`, although this usage should
be discouraged.
This change is NFC in spirit, although not in practice. It does not intend to
support any particular new functionality, but it is probably now possible to use
strings containing null characters in at least some cases. At least one parser
bug is also incidentally fixed. Follow-on PRs will explicitly support and test
strings containing nulls for particular use cases.
The C API still uses `const char*` to represent strings. As strings containing
nulls become better supported by the rest of Binaryen, this will no longer be
sufficient. Updating the C and JS APIs to use pointer, length pairs is left as
future work.
60 files changed, 1259 insertions, 1249 deletions
diff --git a/scripts/gen-s-parser.py b/scripts/gen-s-parser.py index 93fc676e4..3b89820c7 100755 --- a/scripts/gen-s-parser.py +++ b/scripts/gen-s-parser.py @@ -712,8 +712,11 @@ def instruction_parser(new_parser=False): printer = CodePrinter() if not new_parser: - printer.print_line("char op[{}] = {{'\\0'}};".format(inst_length + 1)) - printer.print_line("strncpy(op, s[0]->c_str(), {});".format(inst_length)) + printer.print_line("using namespace std::string_view_literals;") + printer.print_line("auto str = s[0]->str().str;") + printer.print_line("char buf[{}] = {{}};".format(inst_length + 1)) + printer.print_line("memcpy(buf, str.data(), str.size());") + printer.print_line("std::string_view op = {buf, str.size()};") def print_leaf(expr, inst): if new_parser: @@ -726,7 +729,7 @@ def instruction_parser(new_parser=False): printer.print_line("return *ret;") printer.print_line("}") else: - printer.print_line("if (strcmp(op, \"{inst}\") == 0) {{ return {expr}; }}" + printer.print_line("if (op == \"{inst}\"sv) {{ return {expr}; }}" .format(inst=inst, expr=expr)) printer.print_line("goto parse_error;") diff --git a/src/abi/js.h b/src/abi/js.h index 60531803d..735f71af7 100644 --- a/src/abi/js.h +++ b/src/abi/js.h @@ -37,8 +37,6 @@ inline std::string getLegalizationPass(LegalizationLevel level) { namespace wasm2js { -using IString = cashew::IString; - extern IString SCRATCH_LOAD_I32; extern IString SCRATCH_STORE_I32; extern IString SCRATCH_LOAD_F32; diff --git a/src/asmjs/shared-constants.cpp b/src/asmjs/shared-constants.cpp index 6cb350f9f..57b9c4f87 100644 --- a/src/asmjs/shared-constants.cpp +++ b/src/asmjs/shared-constants.cpp @@ -18,8 +18,6 @@ namespace wasm { -using IString = cashew::IString; - IString TOPMOST("topmost"); IString INT8ARRAY("Int8Array"); IString INT16ARRAY("Int16Array"); diff --git a/src/asmjs/shared-constants.h b/src/asmjs/shared-constants.h index 753b34c5d..e199b1361 100644 --- a/src/asmjs/shared-constants.h +++ b/src/asmjs/shared-constants.h @@ -17,12 +17,10 @@ #ifndef wasm_asmjs_shared_constants_h #define wasm_asmjs_shared_constants_h -#include "emscripten-optimizer/istring.h" +#include "support/istring.h" namespace wasm { -using IString = cashew::IString; - extern IString TOPMOST; extern IString INT8ARRAY; extern IString INT16ARRAY; diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index f2908920c..dccc52131 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -100,7 +100,7 @@ BinaryenLiteral toBinaryenLiteral(Literal x) { } } if (heapType.isSignature()) { - ret.func = x.getFunc().c_str(); + ret.func = x.getFunc().str.data(); return ret; } assert(x.isData()); @@ -1892,7 +1892,7 @@ BinaryenExpressionRef BinaryenExpressionCopy(BinaryenExpressionRef expr, const char* BinaryenBlockGetName(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Block>()); - return static_cast<Block*>(expression)->name.c_str(); + return static_cast<Block*>(expression)->name.str.data(); } void BinaryenBlockSetName(BinaryenExpressionRef expr, const char* name) { auto* expression = (Expression*)expr; @@ -1987,7 +1987,7 @@ void BinaryenIfSetIfFalse(BinaryenExpressionRef expr, const char* BinaryenLoopGetName(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Loop>()); - return static_cast<Loop*>(expression)->name.c_str(); + return static_cast<Loop*>(expression)->name.str.data(); } void BinaryenLoopSetName(BinaryenExpressionRef expr, const char* name) { auto* expression = (Expression*)expr; @@ -2011,7 +2011,7 @@ void BinaryenLoopSetBody(BinaryenExpressionRef expr, const char* BinaryenBreakGetName(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Break>()); - return static_cast<Break*>(expression)->name.c_str(); + return static_cast<Break*>(expression)->name.str.data(); } void BinaryenBreakSetName(BinaryenExpressionRef expr, const char* name) { auto* expression = (Expression*)expr; @@ -2054,7 +2054,7 @@ const char* BinaryenSwitchGetNameAt(BinaryenExpressionRef expr, auto* expression = (Expression*)expr; assert(expression->is<Switch>()); assert(index < static_cast<Switch*>(expression)->targets.size()); - return static_cast<Switch*>(expression)->targets[index].c_str(); + return static_cast<Switch*>(expression)->targets[index].str.data(); } void BinaryenSwitchSetNameAt(BinaryenExpressionRef expr, BinaryenIndex index, @@ -2087,12 +2087,12 @@ const char* BinaryenSwitchRemoveNameAt(BinaryenExpressionRef expr, BinaryenIndex index) { auto* expression = (Expression*)expr; assert(expression->is<Switch>()); - return static_cast<Switch*>(expression)->targets.removeAt(index).c_str(); + return static_cast<Switch*>(expression)->targets.removeAt(index).str.data(); } const char* BinaryenSwitchGetDefaultName(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Switch>()); - return static_cast<Switch*>(expression)->default_.c_str(); + return static_cast<Switch*>(expression)->default_.str.data(); } void BinaryenSwitchSetDefaultName(BinaryenExpressionRef expr, const char* name) { @@ -2129,7 +2129,7 @@ void BinaryenSwitchSetValue(BinaryenExpressionRef expr, const char* BinaryenCallGetTarget(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Call>()); - return static_cast<Call*>(expression)->target.c_str(); + return static_cast<Call*>(expression)->target.str.data(); } void BinaryenCallSetTarget(BinaryenExpressionRef expr, const char* target) { auto* expression = (Expression*)expr; @@ -2210,7 +2210,7 @@ void BinaryenCallIndirectSetTarget(BinaryenExpressionRef expr, const char* BinaryenCallIndirectGetTable(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<CallIndirect>()); - return static_cast<CallIndirect*>(expression)->table.c_str(); + return static_cast<CallIndirect*>(expression)->table.str.data(); } void BinaryenCallIndirectSetTable(BinaryenExpressionRef expr, const char* table) { @@ -2350,7 +2350,7 @@ void BinaryenLocalSetSetValue(BinaryenExpressionRef expr, const char* BinaryenGlobalGetGetName(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<GlobalGet>()); - return static_cast<GlobalGet*>(expression)->name.c_str(); + return static_cast<GlobalGet*>(expression)->name.str.data(); } void BinaryenGlobalGetSetName(BinaryenExpressionRef expr, const char* name) { auto* expression = (Expression*)expr; @@ -2362,7 +2362,7 @@ void BinaryenGlobalGetSetName(BinaryenExpressionRef expr, const char* name) { const char* BinaryenGlobalSetGetName(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<GlobalSet>()); - return static_cast<GlobalSet*>(expression)->name.c_str(); + return static_cast<GlobalSet*>(expression)->name.str.data(); } void BinaryenGlobalSetSetName(BinaryenExpressionRef expr, const char* name) { auto* expression = (Expression*)expr; @@ -2386,7 +2386,7 @@ void BinaryenGlobalSetSetValue(BinaryenExpressionRef expr, const char* BinaryenTableGetGetTable(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<TableGet>()); - return static_cast<TableGet*>(expression)->table.c_str(); + return static_cast<TableGet*>(expression)->table.str.data(); } void BinaryenTableGetSetTable(BinaryenExpressionRef expr, const char* table) { auto* expression = (Expression*)expr; @@ -2410,7 +2410,7 @@ void BinaryenTableGetSetIndex(BinaryenExpressionRef expr, const char* BinaryenTableSetGetTable(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<TableSet>()); - return static_cast<TableSet*>(expression)->table.c_str(); + return static_cast<TableSet*>(expression)->table.str.data(); } void BinaryenTableSetSetTable(BinaryenExpressionRef expr, const char* table) { auto* expression = (Expression*)expr; @@ -2446,7 +2446,7 @@ void BinaryenTableSetSetValue(BinaryenExpressionRef expr, const char* BinaryenTableSizeGetTable(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<TableSize>()); - return static_cast<TableSize*>(expression)->table.c_str(); + return static_cast<TableSize*>(expression)->table.str.data(); } void BinaryenTableSizeSetTable(BinaryenExpressionRef expr, const char* table) { auto* expression = (Expression*)expr; @@ -2458,7 +2458,7 @@ void BinaryenTableSizeSetTable(BinaryenExpressionRef expr, const char* table) { const char* BinaryenTableGrowGetTable(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<TableGrow>()); - return static_cast<TableGrow*>(expression)->table.c_str(); + return static_cast<TableGrow*>(expression)->table.str.data(); } void BinaryenTableGrowSetTable(BinaryenExpressionRef expr, const char* table) { auto* expression = (Expression*)expr; @@ -3547,7 +3547,7 @@ void BinaryenRefAsSetValue(BinaryenExpressionRef expr, const char* BinaryenRefFuncGetFunc(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<RefFunc>()); - return static_cast<RefFunc*>(expression)->func.c_str(); + return static_cast<RefFunc*>(expression)->func.str.data(); } void BinaryenRefFuncSetFunc(BinaryenExpressionRef expr, const char* funcName) { auto* expression = (Expression*)expr; @@ -3581,7 +3581,7 @@ void BinaryenRefEqSetRight(BinaryenExpressionRef expr, const char* BinaryenTryGetName(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Try>()); - return static_cast<Try*>(expression)->name.c_str(); + return static_cast<Try*>(expression)->name.str.data(); } void BinaryenTrySetName(BinaryenExpressionRef expr, const char* name) { auto* expression = (Expression*)expr; @@ -3615,7 +3615,7 @@ const char* BinaryenTryGetCatchTagAt(BinaryenExpressionRef expr, auto* expression = (Expression*)expr; assert(expression->is<Try>()); assert(index < static_cast<Try*>(expression)->catchTags.size()); - return static_cast<Try*>(expression)->catchTags[index].c_str(); + return static_cast<Try*>(expression)->catchTags[index].str.data(); } void BinaryenTrySetCatchTagAt(BinaryenExpressionRef expr, BinaryenIndex index, @@ -3648,7 +3648,7 @@ const char* BinaryenTryRemoveCatchTagAt(BinaryenExpressionRef expr, BinaryenIndex index) { auto* expression = (Expression*)expr; assert(expression->is<Try>()); - return static_cast<Try*>(expression)->catchTags.removeAt(index).c_str(); + return static_cast<Try*>(expression)->catchTags.removeAt(index).str.data(); } BinaryenExpressionRef BinaryenTryGetCatchBodyAt(BinaryenExpressionRef expr, BinaryenIndex index) { @@ -3699,7 +3699,7 @@ bool BinaryenTryHasCatchAll(BinaryenExpressionRef expr) { const char* BinaryenTryGetDelegateTarget(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Try>()); - return static_cast<Try*>(expression)->delegateTarget.c_str(); + return static_cast<Try*>(expression)->delegateTarget.str.data(); } void BinaryenTrySetDelegateTarget(BinaryenExpressionRef expr, const char* delegateTarget) { @@ -3716,7 +3716,7 @@ bool BinaryenTryIsDelegate(BinaryenExpressionRef expr) { const char* BinaryenThrowGetTag(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Throw>()); - return static_cast<Throw*>(expression)->tag.c_str(); + return static_cast<Throw*>(expression)->tag.str.data(); } void BinaryenThrowSetTag(BinaryenExpressionRef expr, const char* tagName) { auto* expression = (Expression*)expr; @@ -3773,7 +3773,7 @@ BinaryenExpressionRef BinaryenThrowRemoveOperandAt(BinaryenExpressionRef expr, const char* BinaryenRethrowGetTarget(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<Rethrow>()); - return static_cast<Rethrow*>(expression)->target.c_str(); + return static_cast<Rethrow*>(expression)->target.str.data(); } void BinaryenRethrowSetTarget(BinaryenExpressionRef expr, const char* target) { auto* expression = (Expression*)expr; @@ -4020,7 +4020,7 @@ void BinaryenBrOnSetOp(BinaryenExpressionRef expr, BinaryenOp op) { const char* BinaryenBrOnGetName(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<BrOn>()); - return static_cast<BrOn*>(expression)->name.c_str(); + return static_cast<BrOn*>(expression)->name.str.data(); } void BinaryenBrOnSetName(BinaryenExpressionRef expr, const char* nameStr) { auto* expression = (Expression*)expr; @@ -4453,7 +4453,7 @@ void BinaryenStringNewSetEnd(BinaryenExpressionRef expr, const char* BinaryenStringConstGetString(BinaryenExpressionRef expr) { auto* expression = (Expression*)expr; assert(expression->is<StringConst>()); - return static_cast<StringConst*>(expression)->string.c_str(); + return static_cast<StringConst*>(expression)->string.str.data(); } void BinaryenStringConstSetString(BinaryenExpressionRef expr, const char* stringStr) { @@ -5171,7 +5171,7 @@ const char* BinaryenElementSegmentGetData(BinaryenElementSegmentRef elem, if (data[dataId]->is<RefNull>()) { return NULL; } else if (auto* get = data[dataId]->dynCast<RefFunc>()) { - return get->func.c_str(); + return get->func.str.data(); } else { Fatal() << "invalid expression in segment data."; } @@ -5265,7 +5265,7 @@ BinaryenIndex BinaryenMemoryGetInitial(BinaryenModuleRef module, const char* name) { // Maintaining compatibility for instructions with a single memory if (name == nullptr && module->memories.size() == 1) { - name = module->memories[0]->name.c_str(); + name = module->memories[0]->name.str.data(); } auto* memory = ((Module*)module)->getMemoryOrNull(name); if (memory == nullptr) { @@ -5276,7 +5276,7 @@ BinaryenIndex BinaryenMemoryGetInitial(BinaryenModuleRef module, bool BinaryenMemoryHasMax(BinaryenModuleRef module, const char* name) { // Maintaining compatibility for instructions with a single memory if (name == nullptr && module->memories.size() == 1) { - name = module->memories[0]->name.c_str(); + name = module->memories[0]->name.str.data(); } auto* memory = ((Module*)module)->getMemoryOrNull(name); if (memory == nullptr) { @@ -5287,7 +5287,7 @@ bool BinaryenMemoryHasMax(BinaryenModuleRef module, const char* name) { BinaryenIndex BinaryenMemoryGetMax(BinaryenModuleRef module, const char* name) { // Maintaining compatibility for instructions with a single memory if (name == nullptr && module->memories.size() == 1) { - name = module->memories[0]->name.c_str(); + name = module->memories[0]->name.str.data(); } auto* memory = ((Module*)module)->getMemoryOrNull(name); if (memory == nullptr) { @@ -5299,14 +5299,14 @@ const char* BinaryenMemoryImportGetModule(BinaryenModuleRef module, const char* name) { // Maintaining compatibility for instructions with a single memory if (name == nullptr && module->memories.size() == 1) { - name = module->memories[0]->name.c_str(); + name = module->memories[0]->name.str.data(); } auto* memory = ((Module*)module)->getMemoryOrNull(name); if (memory == nullptr) { Fatal() << "invalid memory '" << name << "'."; } if (memory->imported()) { - return memory->module.c_str(); + return memory->module.str.data(); } else { return ""; } @@ -5315,14 +5315,14 @@ const char* BinaryenMemoryImportGetBase(BinaryenModuleRef module, const char* name) { // Maintaining compatibility for instructions with a single memory if (name == nullptr && module->memories.size() == 1) { - name = module->memories[0]->name.c_str(); + name = module->memories[0]->name.str.data(); } auto* memory = ((Module*)module)->getMemoryOrNull(name); if (memory == nullptr) { Fatal() << "invalid memory '" << name << "'."; } if (memory->imported()) { - return memory->base.c_str(); + return memory->base.str.data(); } else { return ""; } @@ -5330,7 +5330,7 @@ const char* BinaryenMemoryImportGetBase(BinaryenModuleRef module, bool BinaryenMemoryIsShared(BinaryenModuleRef module, const char* name) { // Maintaining compatibility for instructions with a single memory if (name == nullptr && module->memories.size() == 1) { - name = module->memories[0]->name.c_str(); + name = module->memories[0]->name.str.data(); } auto* memory = ((Module*)module)->getMemoryOrNull(name); if (memory == nullptr) { @@ -5341,7 +5341,7 @@ bool BinaryenMemoryIsShared(BinaryenModuleRef module, const char* name) { bool BinaryenMemoryIs64(BinaryenModuleRef module, const char* name) { // Maintaining compatibility for instructions with a single memory if (name == nullptr && module->memories.size() == 1) { - name = module->memories[0]->name.c_str(); + name = module->memories[0]->name.str.data(); } auto* memory = ((Module*)module)->getMemoryOrNull(name); if (memory == nullptr) { @@ -5491,7 +5491,7 @@ const char* BinaryenGetPassArgument(const char* key) { return nullptr; } // internalize the string so it remains valid while the module is - return Name(it->second).c_str(); + return Name(it->second).str.data(); } void BinaryenSetPassArgument(const char* key, const char* value) { @@ -5726,7 +5726,7 @@ const char* BinaryenModuleGetDebugInfoFileName(BinaryenModuleRef module, // TODO: add BinaryenFunctionGetType const char* BinaryenFunctionGetName(BinaryenFunctionRef func) { - return ((Function*)func)->name.c_str(); + return ((Function*)func)->name.str.data(); } BinaryenType BinaryenFunctionGetParams(BinaryenFunctionRef func) { return ((Function*)func)->getParams().getID(); @@ -5752,7 +5752,7 @@ bool BinaryenFunctionHasLocalName(BinaryenFunctionRef func, } const char* BinaryenFunctionGetLocalName(BinaryenFunctionRef func, BinaryenIndex index) { - return ((Function*)func)->getLocalName(index).str; + return ((Function*)func)->getLocalName(index).str.data(); } void BinaryenFunctionSetLocalName(BinaryenFunctionRef func, BinaryenIndex index, @@ -5802,7 +5802,7 @@ void BinaryenFunctionSetDebugLocation(BinaryenFunctionRef func, // const char* BinaryenTableGetName(BinaryenTableRef table) { - return ((Table*)table)->name.c_str(); + return ((Table*)table)->name.str.data(); } void BinaryenTableSetName(BinaryenTableRef table, const char* name) { ((Table*)table)->name = name; @@ -5827,14 +5827,14 @@ void BinaryenTableSetMax(BinaryenTableRef table, BinaryenIndex max) { // =========== ElementSegment operations =========== // const char* BinaryenElementSegmentGetName(BinaryenElementSegmentRef elem) { - return ((ElementSegment*)elem)->name.c_str(); + return ((ElementSegment*)elem)->name.str.data(); } void BinaryenElementSegmentSetName(BinaryenElementSegmentRef elem, const char* name) { ((ElementSegment*)elem)->name = name; } const char* BinaryenElementSegmentGetTable(BinaryenElementSegmentRef elem) { - return ((ElementSegment*)elem)->table.c_str(); + return ((ElementSegment*)elem)->table.str.data(); } void BinaryenElementSegmentSetTable(BinaryenElementSegmentRef elem, const char* table) { @@ -5849,7 +5849,7 @@ bool BinaryenElementSegmentIsPassive(BinaryenElementSegmentRef elem) { // const char* BinaryenGlobalGetName(BinaryenGlobalRef global) { - return ((Global*)global)->name.c_str(); + return ((Global*)global)->name.str.data(); } BinaryenType BinaryenGlobalGetType(BinaryenGlobalRef global) { return ((Global*)global)->type.getID(); @@ -5866,7 +5866,7 @@ BinaryenExpressionRef BinaryenGlobalGetInitExpr(BinaryenGlobalRef global) { // const char* BinaryenTagGetName(BinaryenTagRef tag) { - return ((Tag*)tag)->name.c_str(); + return ((Tag*)tag)->name.str.data(); } BinaryenType BinaryenTagGetParams(BinaryenTagRef tag) { return ((Tag*)tag)->sig.params.getID(); @@ -5883,7 +5883,7 @@ BinaryenType BinaryenTagGetResults(BinaryenTagRef tag) { const char* BinaryenFunctionImportGetModule(BinaryenFunctionRef import) { auto* func = (Function*)import; if (func->imported()) { - return func->module.c_str(); + return func->module.str.data(); } else { return ""; } @@ -5891,7 +5891,7 @@ const char* BinaryenFunctionImportGetModule(BinaryenFunctionRef import) { const char* BinaryenTableImportGetModule(BinaryenTableRef import) { auto* table = (Table*)import; if (table->imported()) { - return table->module.c_str(); + return table->module.str.data(); } else { return ""; } @@ -5899,7 +5899,7 @@ const char* BinaryenTableImportGetModule(BinaryenTableRef import) { const char* BinaryenGlobalImportGetModule(BinaryenGlobalRef import) { auto* global = (Global*)import; if (global->imported()) { - return global->module.c_str(); + return global->module.str.data(); } else { return ""; } @@ -5907,7 +5907,7 @@ const char* BinaryenGlobalImportGetModule(BinaryenGlobalRef import) { const char* BinaryenTagImportGetModule(BinaryenTagRef import) { auto* tag = (Tag*)import; if (tag->imported()) { - return tag->module.c_str(); + return tag->module.str.data(); } else { return ""; } @@ -5915,7 +5915,7 @@ const char* BinaryenTagImportGetModule(BinaryenTagRef import) { const char* BinaryenFunctionImportGetBase(BinaryenFunctionRef import) { auto* func = (Function*)import; if (func->imported()) { - return func->base.c_str(); + return func->base.str.data(); } else { return ""; } @@ -5923,7 +5923,7 @@ const char* BinaryenFunctionImportGetBase(BinaryenFunctionRef import) { const char* BinaryenTableImportGetBase(BinaryenTableRef import) { auto* table = (Table*)import; if (table->imported()) { - return table->base.c_str(); + return table->base.str.data(); } else { return ""; } @@ -5931,7 +5931,7 @@ const char* BinaryenTableImportGetBase(BinaryenTableRef import) { const char* BinaryenGlobalImportGetBase(BinaryenGlobalRef import) { auto* global = (Global*)import; if (global->imported()) { - return global->base.c_str(); + return global->base.str.data(); } else { return ""; } @@ -5939,7 +5939,7 @@ const char* BinaryenGlobalImportGetBase(BinaryenGlobalRef import) { const char* BinaryenTagImportGetBase(BinaryenTagRef import) { auto* tag = (Tag*)import; if (tag->imported()) { - return tag->base.c_str(); + return tag->base.str.data(); } else { return ""; } @@ -5953,10 +5953,10 @@ BinaryenExternalKind BinaryenExportGetKind(BinaryenExportRef export_) { return BinaryenExternalKind(((Export*)export_)->kind); } const char* BinaryenExportGetName(BinaryenExportRef export_) { - return ((Export*)export_)->name.c_str(); + return ((Export*)export_)->name.str.data(); } const char* BinaryenExportGetValue(BinaryenExportRef export_) { - return ((Export*)export_)->value.c_str(); + return ((Export*)export_)->value.str.data(); } // diff --git a/src/emscripten-optimizer/istring.h b/src/emscripten-optimizer/istring.h deleted file mode 100644 index 69df761fd..000000000 --- a/src/emscripten-optimizer/istring.h +++ /dev/null @@ -1,218 +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. - */ - -// Interned String type, 100% interned on creation. Comparisons are always just -// a pointer comparison - -#ifndef wasm_istring_h -#define wasm_istring_h - -#include <set> -#include <unordered_map> -#include <unordered_set> - -#include <assert.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "support/threads.h" -#include "support/utilities.h" - -namespace cashew { - -struct IString { - const char* str = nullptr; - - static size_t - hash_c(const char* str) { // see http://www.cse.yorku.ca/~oz/hash.html - unsigned int hash = 5381; - int c; - while ((c = *str++)) { - hash = ((hash << 5) + hash) ^ c; - } - return (size_t)hash; - } - - class CStringHash { - public: - size_t operator()(const char* str) const { return IString::hash_c(str); } - }; - class CStringEqual { - public: - bool operator()(const char* x, const char* y) const { - return strcmp(x, y) == 0; - } - }; - - IString() = default; - // if reuse=true, then input is assumed to remain alive; not copied - IString(const char* s, bool reuse = true) { - assert(s); - set(s, reuse); - } - - void set(const char* s, bool reuse = true) { - typedef std::unordered_set<const char*, CStringHash, CStringEqual> - StringSet; - // one global store of strings per thread, we must not access this - // in parallel - thread_local static StringSet strings; - - auto existing = strings.find(s); - - if (existing == strings.end()) { - // if the string isn't already known, we must use a single global - // storage location, guarded by a mutex, so each string is allocated - // exactly once - static std::mutex mutex; - std::unique_lock<std::mutex> lock(mutex); - // a single global set contains the actual strings, so we allocate each - // one exactly once. - static StringSet globalStrings; - auto globalExisting = globalStrings.find(s); - if (globalExisting == globalStrings.end()) { - if (!reuse) { - static std::vector<std::unique_ptr<std::string>> allocated; - allocated.emplace_back(wasm::make_unique<std::string>(s)); - s = allocated.back()->c_str(); // we'll never modify it, so this is ok - } - // insert into global set - globalStrings.insert(s); - } else { - s = *globalExisting; - } - // add the string to our thread-local set - strings.insert(s); - } else { - s = *existing; - } - - str = s; - } - - void set(const IString& s) { str = s.str; } - - void clear() { str = nullptr; } - - bool operator==(const IString& other) const { - // assert((str == other.str) == !strcmp(str, other.str)); - return str == other.str; // fast! - } - bool operator!=(const IString& other) const { - // assert((str == other.str) == !strcmp(str, other.str)); - return str != other.str; // fast! - } - bool operator<(const IString& other) const { - return strcmp(str ? str : "", other.str ? other.str : "") < 0; - } - - char operator[](int x) const { return str[x]; } - - bool operator!() const { // no string, or empty string - return !str || str[0] == 0; - } - - const char* c_str() const { return str; } - bool equals(const char* other) const { return !strcmp(str, other); } - - bool is() const { return str != nullptr; } - bool isNull() const { return str == nullptr; } - - const char* stripPrefix(const char* prefix) const { - const char* ptr = str; - while (true) { - if (*prefix == 0) { - return ptr; - } - if (*ptr == 0) { - return nullptr; - } - if (*ptr++ != *prefix++) { - return nullptr; - } - } - } - - bool startsWith(const char* prefix) const { - return stripPrefix(prefix) != nullptr; - } - bool startsWith(const IString& prefix) const { - return startsWith(prefix.str); - } - - size_t size() const { return str ? strlen(str) : 0; } -}; - -} // namespace cashew - -// Utilities for creating hashmaps/sets over IStrings - -namespace std { - -template<> struct hash<cashew::IString> { - size_t operator()(const cashew::IString& str) const { - return std::hash<size_t>{}(size_t(str.str)); - } -}; - -template<> struct equal_to<cashew::IString> { - bool operator()(const cashew::IString& x, const cashew::IString& y) const { - return x == y; - } -}; - -} // namespace std - -namespace cashew { - -// IStringSet - -class IStringSet : public std::unordered_set<IString> { - std::vector<char> data; - -public: - IStringSet() = default; - IStringSet(const char* init) { // comma-delimited list - int size = strlen(init) + 1; - data.resize(size); - char* curr = &data[0]; - strncpy(curr, init, size); - while (1) { - char* end = strchr(curr, ' '); - if (end) { - *end = 0; - } - insert(curr); - if (!end) { - break; - } - curr = end + 1; - } - } - - bool has(const IString& str) { return count(str) > 0; } -}; - -class IOrderedStringSet : public std::set<IString> { -public: - bool has(const IString& str) { return count(str) > 0; } -}; - -} // namespace cashew - -#endif // wasm_istring_h diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 8208f6f47..9ca66441a 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -19,8 +19,6 @@ #include "optimizer.h" #include "support/safe_integer.h" -using namespace cashew; - IString JS_FLOAT_ZERO; IString SIMD_INT8X16_CHECK("SIMD_Int8x16_check"); diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h index 132ff6fb8..9e5c7afe8 100644 --- a/src/emscripten-optimizer/optimizer.h +++ b/src/emscripten-optimizer/optimizer.h @@ -20,6 +20,7 @@ #include "simple_ast.h" using namespace cashew; +using IString = wasm::IString; extern IString JS_FLOAT_ZERO; diff --git a/src/emscripten-optimizer/parser.cpp b/src/emscripten-optimizer/parser.cpp index 016966299..533043232 100644 --- a/src/emscripten-optimizer/parser.cpp +++ b/src/emscripten-optimizer/parser.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <unordered_map> + #include "parser.h" namespace cashew { diff --git a/src/emscripten-optimizer/parser.h b/src/emscripten-optimizer/parser.h index c4d596058..8c3f36427 100644 --- a/src/emscripten-optimizer/parser.h +++ b/src/emscripten-optimizer/parser.h @@ -30,11 +30,46 @@ #include <limits> #include <vector> -#include "istring.h" +#include "support/istring.h" #include "support/safe_integer.h" namespace cashew { +using IString = wasm::IString; + +// IStringSet + +class IStringSet : public std::unordered_set<IString> { + std::vector<char> data; + +public: + IStringSet() = default; + IStringSet(const char* init) { // comma-delimited list + int size = strlen(init) + 1; + data.resize(size); + char* curr = &data[0]; + strncpy(curr, init, size); + while (1) { + char* end = strchr(curr, ' '); + if (end) { + *end = 0; + } + insert(curr); + if (!end) { + break; + } + curr = end + 1; + } + } + + bool has(const IString& str) { return count(str) > 0; } +}; + +class IOrderedStringSet : public std::set<IString> { +public: + bool has(const IString& str) { return count(str) > 0; } +}; + // common strings extern IString TOPLEVEL; @@ -233,11 +268,11 @@ template<class NodeRef, class Builder> class Parser { src++; } if (*src == 0) { - str.set(start); + str = IString(start); } else { char temp = *src; *src = 0; - str.set(start, false); + str = IString(start, false); *src = temp; } type = keywords.has(str) ? KEYWORD : IDENT; @@ -333,11 +368,11 @@ template<class NodeRef, class Builder> class Parser { default: abort(); } - size = strlen(str.str); + size = str.size(); #ifndef NDEBUG char temp = start[size]; start[size] = 0; - assert(strcmp(str.str, start) == 0); + assert(str.str == start); start[size] = temp; #endif type = OPERATOR; @@ -346,13 +381,13 @@ template<class NodeRef, class Builder> class Parser { type = SEPARATOR; char temp = src[1]; src[1] = 0; - str.set(src, false); + str = IString(src, false); src[1] = temp; src++; } else if (*src == '"' || *src == '\'') { char* end = strchr(src + 1, *src); *end = 0; - str.set(src + 1); + str = IString(src + 1); src = end + 1; type = STRING; } else { diff --git a/src/emscripten-optimizer/simple_ast.cpp b/src/emscripten-optimizer/simple_ast.cpp index 6afa0a66e..086d504ba 100644 --- a/src/emscripten-optimizer/simple_ast.cpp +++ b/src/emscripten-optimizer/simple_ast.cpp @@ -24,13 +24,11 @@ Ref& Ref::operator[](unsigned x) { return (*get())[x]; } Ref& Ref::operator[](IString x) { return (*get())[x]; } -bool Ref::operator==(const char* str) { - return get()->isString() && !strcmp(get()->str.str, str); +bool Ref::operator==(std::string_view str) { + return get()->isString() && get()->str == str; } -bool Ref::operator!=(const char* str) { - return get()->isString() ? !!strcmp(get()->str.str, str) : true; -} +bool Ref::operator!=(std::string_view str) { return !(*this == str); } bool Ref::operator==(const IString& str) { return get()->isString() && get()->str == str; @@ -81,8 +79,8 @@ void Value::stringify(std::ostream& os, bool pretty) { } switch (type) { case String: { - if (str.str) { - os << '"' << str.str << '"'; + if (str) { + os << '"' << str << '"'; } else { os << "\"(null)\""; } @@ -147,7 +145,7 @@ void Value::stringify(std::ostream& os, bool pretty) { } } indentify(); - os << '"' << i.first.c_str() << "\": "; + os << '"' << i.first << "\": "; i.second->stringify(os, pretty); } if (pretty) { diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index 64db04d79..60399d6d2 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -63,8 +63,9 @@ struct Ref { Ref& operator[](IString x); // special conveniences - bool operator==(const char* str); // comparison to string, which is by value - bool operator!=(const char* str); + bool + operator==(std::string_view str); // comparison to string, which is by value + bool operator!=(std::string_view str); bool operator==(const IString& str); bool operator!=(const IString& str); // prevent Ref == number, which is potentially ambiguous; use ->getNumber() == @@ -163,13 +164,13 @@ struct Value { Value& setString(const char* s) { free(); type = String; - str.set(s); + str = IString(s); return *this; } Value& setString(const IString& s) { free(); type = String; - str.set(s); + str = s; return *this; } Value& setNumber(double n) { @@ -233,7 +234,7 @@ struct Value { const char* getCString() { assert(isString()); - return str.str; + return str.str.data(); } IString& getIString() { assert(isString()); @@ -817,7 +818,7 @@ struct JSPrinter { break; } default: { - errv("cannot yet print %s\n", type.str); + errv("cannot yet print %s\n", type.str.data()); abort(); } } @@ -908,7 +909,7 @@ struct JSPrinter { void printAssignName(Ref node) { auto* assign = node->asAssignName(); - emit(assign->target().c_str()); + emit(assign->target().str.data()); space(); emit('='); space(); @@ -1472,10 +1473,10 @@ struct JSPrinter { needQuote = true; str = args[i][0][1]->getCString(); } else if (args[i][0][0] == GETTER) { - getterSetter = GETTER.c_str(); + getterSetter = GETTER.str.data(); str = args[i][0][1]->getCString(); } else if (args[i][0][0] == SETTER) { - getterSetter = SETTER.c_str(); + getterSetter = SETTER.str.data(); str = args[i][0][1]->getCString(); setterParam = args[i][0][2]->getCString(); } else { diff --git a/src/gen-s-parser.inc b/src/gen-s-parser.inc index 4803f60b5..f2e1fee9a 100644 --- a/src/gen-s-parser.inc +++ b/src/gen-s-parser.inc @@ -4,28 +4,31 @@ #ifdef INSTRUCTION_PARSER #undef INSTRUCTION_PARSER -char op[33] = {'\0'}; -strncpy(op, s[0]->c_str(), 32); +using namespace std::string_view_literals; +auto str = s[0]->str().str; +char buf[33] = {}; +memcpy(buf, str.data(), str.size()); +std::string_view op = {buf, str.size()}; switch (op[0]) { case 'a': { switch (op[1]) { case 'r': { switch (op[6]) { case 'c': - if (strcmp(op, "array.copy") == 0) { return makeArrayCopy(s); } + if (op == "array.copy"sv) { return makeArrayCopy(s); } goto parse_error; case 'g': { switch (op[9]) { case '\0': - if (strcmp(op, "array.get") == 0) { return makeArrayGet(s); } + if (op == "array.get"sv) { return makeArrayGet(s); } goto parse_error; case '_': { switch (op[10]) { case 's': - if (strcmp(op, "array.get_s") == 0) { return makeArrayGet(s, true); } + if (op == "array.get_s"sv) { return makeArrayGet(s, true); } goto parse_error; case 'u': - if (strcmp(op, "array.get_u") == 0) { return makeArrayGet(s, false); } + if (op == "array.get_u"sv) { return makeArrayGet(s, false); } goto parse_error; default: goto parse_error; } @@ -34,30 +37,30 @@ switch (op[0]) { } } case 'i': - if (strcmp(op, "array.init_static") == 0) { return makeArrayInitStatic(s); } + if (op == "array.init_static"sv) { return makeArrayInitStatic(s); } goto parse_error; case 'l': - if (strcmp(op, "array.len") == 0) { return makeArrayLen(s); } + if (op == "array.len"sv) { return makeArrayLen(s); } goto parse_error; case 'n': { switch (op[9]) { case '\0': - if (strcmp(op, "array.new") == 0) { return makeArrayNewStatic(s, false); } + if (op == "array.new"sv) { return makeArrayNewStatic(s, false); } goto parse_error; case '_': - if (strcmp(op, "array.new_default") == 0) { return makeArrayNewStatic(s, true); } + if (op == "array.new_default"sv) { return makeArrayNewStatic(s, true); } goto parse_error; default: goto parse_error; } } case 's': - if (strcmp(op, "array.set") == 0) { return makeArraySet(s); } + if (op == "array.set"sv) { return makeArraySet(s); } goto parse_error; default: goto parse_error; } } case 't': - if (strcmp(op, "atomic.fence") == 0) { return makeAtomicFence(s); } + if (op == "atomic.fence"sv) { return makeAtomicFence(s); } goto parse_error; default: goto parse_error; } @@ -65,37 +68,37 @@ switch (op[0]) { case 'b': { switch (op[1]) { case 'l': - if (strcmp(op, "block") == 0) { return makeBlock(s); } + if (op == "block"sv) { return makeBlock(s); } goto parse_error; case 'r': { switch (op[2]) { case '\0': - if (strcmp(op, "br") == 0) { return makeBreak(s); } + if (op == "br"sv) { return makeBreak(s); } goto parse_error; case '_': { switch (op[3]) { case 'i': - if (strcmp(op, "br_if") == 0) { return makeBreak(s); } + if (op == "br_if"sv) { return makeBreak(s); } goto parse_error; case 'o': { switch (op[6]) { case 'c': { switch (op[10]) { case '\0': - if (strcmp(op, "br_on_cast") == 0) { return makeBrOn(s, BrOnCast); } + if (op == "br_on_cast"sv) { return makeBrOn(s, BrOnCast); } goto parse_error; case '_': { switch (op[11]) { case 'f': - if (strcmp(op, "br_on_cast_fail") == 0) { return makeBrOn(s, BrOnCastFail); } + if (op == "br_on_cast_fail"sv) { return makeBrOn(s, BrOnCastFail); } goto parse_error; case 's': { switch (op[17]) { case '\0': - if (strcmp(op, "br_on_cast_static") == 0) { return makeBrOnStatic(s, BrOnCast); } + if (op == "br_on_cast_static"sv) { return makeBrOnStatic(s, BrOnCast); } goto parse_error; case '_': - if (strcmp(op, "br_on_cast_static_fail") == 0) { return makeBrOnStatic(s, BrOnCastFail); } + if (op == "br_on_cast_static_fail"sv) { return makeBrOnStatic(s, BrOnCastFail); } goto parse_error; default: goto parse_error; } @@ -107,35 +110,35 @@ switch (op[0]) { } } case 'd': - if (strcmp(op, "br_on_data") == 0) { return makeBrOn(s, BrOnData); } + if (op == "br_on_data"sv) { return makeBrOn(s, BrOnData); } goto parse_error; case 'f': - if (strcmp(op, "br_on_func") == 0) { return makeBrOn(s, BrOnFunc); } + if (op == "br_on_func"sv) { return makeBrOn(s, BrOnFunc); } goto parse_error; case 'i': - if (strcmp(op, "br_on_i31") == 0) { return makeBrOn(s, BrOnI31); } + if (op == "br_on_i31"sv) { return makeBrOn(s, BrOnI31); } goto parse_error; case 'n': { switch (op[7]) { case 'o': { switch (op[10]) { case 'd': - if (strcmp(op, "br_on_non_data") == 0) { return makeBrOn(s, BrOnNonData); } + if (op == "br_on_non_data"sv) { return makeBrOn(s, BrOnNonData); } goto parse_error; case 'f': - if (strcmp(op, "br_on_non_func") == 0) { return makeBrOn(s, BrOnNonFunc); } + if (op == "br_on_non_func"sv) { return makeBrOn(s, BrOnNonFunc); } goto parse_error; case 'i': - if (strcmp(op, "br_on_non_i31") == 0) { return makeBrOn(s, BrOnNonI31); } + if (op == "br_on_non_i31"sv) { return makeBrOn(s, BrOnNonI31); } goto parse_error; case 'n': - if (strcmp(op, "br_on_non_null") == 0) { return makeBrOn(s, BrOnNonNull); } + if (op == "br_on_non_null"sv) { return makeBrOn(s, BrOnNonNull); } goto parse_error; default: goto parse_error; } } case 'u': - if (strcmp(op, "br_on_null") == 0) { return makeBrOn(s, BrOnNull); } + if (op == "br_on_null"sv) { return makeBrOn(s, BrOnNull); } goto parse_error; default: goto parse_error; } @@ -144,7 +147,7 @@ switch (op[0]) { } } case 't': - if (strcmp(op, "br_table") == 0) { return makeBreakTable(s); } + if (op == "br_table"sv) { return makeBreakTable(s); } goto parse_error; default: goto parse_error; } @@ -158,15 +161,15 @@ switch (op[0]) { case 'c': { switch (op[4]) { case '\0': - if (strcmp(op, "call") == 0) { return makeCall(s, /*isReturn=*/false); } + if (op == "call"sv) { return makeCall(s, /*isReturn=*/false); } goto parse_error; case '_': { switch (op[5]) { case 'i': - if (strcmp(op, "call_indirect") == 0) { return makeCallIndirect(s, /*isReturn=*/false); } + if (op == "call_indirect"sv) { return makeCallIndirect(s, /*isReturn=*/false); } goto parse_error; case 'r': - if (strcmp(op, "call_ref") == 0) { return makeCallRef(s, /*isReturn=*/false); } + if (op == "call_ref"sv) { return makeCallRef(s, /*isReturn=*/false); } goto parse_error; default: goto parse_error; } @@ -177,10 +180,10 @@ switch (op[0]) { case 'd': { switch (op[1]) { case 'a': - if (strcmp(op, "data.drop") == 0) { return makeDataDrop(s); } + if (op == "data.drop"sv) { return makeDataDrop(s); } goto parse_error; case 'r': - if (strcmp(op, "drop") == 0) { return makeDrop(s); } + if (op == "drop"sv) { return makeDrop(s); } goto parse_error; default: goto parse_error; } @@ -188,15 +191,15 @@ switch (op[0]) { case 'e': { switch (op[1]) { case 'l': - if (strcmp(op, "else") == 0) { return makeThenOrElse(s); } + if (op == "else"sv) { return makeThenOrElse(s); } goto parse_error; case 'x': { switch (op[7]) { case 'e': - if (strcmp(op, "extern.externalize") == 0) { return makeRefAs(s, ExternExternalize); } + if (op == "extern.externalize"sv) { return makeRefAs(s, ExternExternalize); } goto parse_error; case 'i': - if (strcmp(op, "extern.internalize") == 0) { return makeRefAs(s, ExternInternalize); } + if (op == "extern.internalize"sv) { return makeRefAs(s, ExternInternalize); } goto parse_error; default: goto parse_error; } @@ -213,10 +216,10 @@ switch (op[0]) { case 'a': { switch (op[5]) { case 'b': - if (strcmp(op, "f32.abs") == 0) { return makeUnary(s, UnaryOp::AbsFloat32); } + if (op == "f32.abs"sv) { return makeUnary(s, UnaryOp::AbsFloat32); } goto parse_error; case 'd': - if (strcmp(op, "f32.add") == 0) { return makeBinary(s, BinaryOp::AddFloat32); } + if (op == "f32.add"sv) { return makeBinary(s, BinaryOp::AddFloat32); } goto parse_error; default: goto parse_error; } @@ -224,24 +227,24 @@ switch (op[0]) { case 'c': { switch (op[5]) { case 'e': - if (strcmp(op, "f32.ceil") == 0) { return makeUnary(s, UnaryOp::CeilFloat32); } + if (op == "f32.ceil"sv) { return makeUnary(s, UnaryOp::CeilFloat32); } goto parse_error; case 'o': { switch (op[6]) { case 'n': { switch (op[7]) { case 's': - if (strcmp(op, "f32.const") == 0) { return makeConst(s, Type::f32); } + if (op == "f32.const"sv) { return makeConst(s, Type::f32); } goto parse_error; case 'v': { switch (op[13]) { case '3': { switch (op[16]) { case 's': - if (strcmp(op, "f32.convert_i32_s") == 0) { return makeUnary(s, UnaryOp::ConvertSInt32ToFloat32); } + if (op == "f32.convert_i32_s"sv) { return makeUnary(s, UnaryOp::ConvertSInt32ToFloat32); } goto parse_error; case 'u': - if (strcmp(op, "f32.convert_i32_u") == 0) { return makeUnary(s, UnaryOp::ConvertUInt32ToFloat32); } + if (op == "f32.convert_i32_u"sv) { return makeUnary(s, UnaryOp::ConvertUInt32ToFloat32); } goto parse_error; default: goto parse_error; } @@ -249,10 +252,10 @@ switch (op[0]) { case '6': { switch (op[16]) { case 's': - if (strcmp(op, "f32.convert_i64_s") == 0) { return makeUnary(s, UnaryOp::ConvertSInt64ToFloat32); } + if (op == "f32.convert_i64_s"sv) { return makeUnary(s, UnaryOp::ConvertSInt64ToFloat32); } goto parse_error; case 'u': - if (strcmp(op, "f32.convert_i64_u") == 0) { return makeUnary(s, UnaryOp::ConvertUInt64ToFloat32); } + if (op == "f32.convert_i64_u"sv) { return makeUnary(s, UnaryOp::ConvertUInt64ToFloat32); } goto parse_error; default: goto parse_error; } @@ -264,7 +267,7 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "f32.copysign") == 0) { return makeBinary(s, BinaryOp::CopySignFloat32); } + if (op == "f32.copysign"sv) { return makeBinary(s, BinaryOp::CopySignFloat32); } goto parse_error; default: goto parse_error; } @@ -275,27 +278,27 @@ switch (op[0]) { case 'd': { switch (op[5]) { case 'e': - if (strcmp(op, "f32.demote_f64") == 0) { return makeUnary(s, UnaryOp::DemoteFloat64); } + if (op == "f32.demote_f64"sv) { return makeUnary(s, UnaryOp::DemoteFloat64); } goto parse_error; case 'i': - if (strcmp(op, "f32.div") == 0) { return makeBinary(s, BinaryOp::DivFloat32); } + if (op == "f32.div"sv) { return makeBinary(s, BinaryOp::DivFloat32); } goto parse_error; default: goto parse_error; } } case 'e': - if (strcmp(op, "f32.eq") == 0) { return makeBinary(s, BinaryOp::EqFloat32); } + if (op == "f32.eq"sv) { return makeBinary(s, BinaryOp::EqFloat32); } goto parse_error; case 'f': - if (strcmp(op, "f32.floor") == 0) { return makeUnary(s, UnaryOp::FloorFloat32); } + if (op == "f32.floor"sv) { return makeUnary(s, UnaryOp::FloorFloat32); } goto parse_error; case 'g': { switch (op[5]) { case 'e': - if (strcmp(op, "f32.ge") == 0) { return makeBinary(s, BinaryOp::GeFloat32); } + if (op == "f32.ge"sv) { return makeBinary(s, BinaryOp::GeFloat32); } goto parse_error; case 't': - if (strcmp(op, "f32.gt") == 0) { return makeBinary(s, BinaryOp::GtFloat32); } + if (op == "f32.gt"sv) { return makeBinary(s, BinaryOp::GtFloat32); } goto parse_error; default: goto parse_error; } @@ -303,13 +306,13 @@ switch (op[0]) { case 'l': { switch (op[5]) { case 'e': - if (strcmp(op, "f32.le") == 0) { return makeBinary(s, BinaryOp::LeFloat32); } + if (op == "f32.le"sv) { return makeBinary(s, BinaryOp::LeFloat32); } goto parse_error; case 'o': - if (strcmp(op, "f32.load") == 0) { return makeLoad(s, Type::f32, /*isAtomic=*/false); } + if (op == "f32.load"sv) { return makeLoad(s, Type::f32, /*isAtomic=*/false); } goto parse_error; case 't': - if (strcmp(op, "f32.lt") == 0) { return makeBinary(s, BinaryOp::LtFloat32); } + if (op == "f32.lt"sv) { return makeBinary(s, BinaryOp::LtFloat32); } goto parse_error; default: goto parse_error; } @@ -317,13 +320,13 @@ switch (op[0]) { case 'm': { switch (op[5]) { case 'a': - if (strcmp(op, "f32.max") == 0) { return makeBinary(s, BinaryOp::MaxFloat32); } + if (op == "f32.max"sv) { return makeBinary(s, BinaryOp::MaxFloat32); } goto parse_error; case 'i': - if (strcmp(op, "f32.min") == 0) { return makeBinary(s, BinaryOp::MinFloat32); } + if (op == "f32.min"sv) { return makeBinary(s, BinaryOp::MinFloat32); } goto parse_error; case 'u': - if (strcmp(op, "f32.mul") == 0) { return makeBinary(s, BinaryOp::MulFloat32); } + if (op == "f32.mul"sv) { return makeBinary(s, BinaryOp::MulFloat32); } goto parse_error; default: goto parse_error; } @@ -331,36 +334,36 @@ switch (op[0]) { case 'n': { switch (op[6]) { case '\0': - if (strcmp(op, "f32.ne") == 0) { return makeBinary(s, BinaryOp::NeFloat32); } + if (op == "f32.ne"sv) { return makeBinary(s, BinaryOp::NeFloat32); } goto parse_error; case 'a': - if (strcmp(op, "f32.nearest") == 0) { return makeUnary(s, UnaryOp::NearestFloat32); } + if (op == "f32.nearest"sv) { return makeUnary(s, UnaryOp::NearestFloat32); } goto parse_error; case 'g': - if (strcmp(op, "f32.neg") == 0) { return makeUnary(s, UnaryOp::NegFloat32); } + if (op == "f32.neg"sv) { return makeUnary(s, UnaryOp::NegFloat32); } goto parse_error; default: goto parse_error; } } case 'r': - if (strcmp(op, "f32.reinterpret_i32") == 0) { return makeUnary(s, UnaryOp::ReinterpretInt32); } + if (op == "f32.reinterpret_i32"sv) { return makeUnary(s, UnaryOp::ReinterpretInt32); } goto parse_error; case 's': { switch (op[5]) { case 'q': - if (strcmp(op, "f32.sqrt") == 0) { return makeUnary(s, UnaryOp::SqrtFloat32); } + if (op == "f32.sqrt"sv) { return makeUnary(s, UnaryOp::SqrtFloat32); } goto parse_error; case 't': - if (strcmp(op, "f32.store") == 0) { return makeStore(s, Type::f32, /*isAtomic=*/false); } + if (op == "f32.store"sv) { return makeStore(s, Type::f32, /*isAtomic=*/false); } goto parse_error; case 'u': - if (strcmp(op, "f32.sub") == 0) { return makeBinary(s, BinaryOp::SubFloat32); } + if (op == "f32.sub"sv) { return makeBinary(s, BinaryOp::SubFloat32); } goto parse_error; default: goto parse_error; } } case 't': - if (strcmp(op, "f32.trunc") == 0) { return makeUnary(s, UnaryOp::TruncFloat32); } + if (op == "f32.trunc"sv) { return makeUnary(s, UnaryOp::TruncFloat32); } goto parse_error; default: goto parse_error; } @@ -370,10 +373,10 @@ switch (op[0]) { case 'a': { switch (op[7]) { case 'b': - if (strcmp(op, "f32x4.abs") == 0) { return makeUnary(s, UnaryOp::AbsVecF32x4); } + if (op == "f32x4.abs"sv) { return makeUnary(s, UnaryOp::AbsVecF32x4); } goto parse_error; case 'd': - if (strcmp(op, "f32x4.add") == 0) { return makeBinary(s, BinaryOp::AddVecF32x4); } + if (op == "f32x4.add"sv) { return makeBinary(s, BinaryOp::AddVecF32x4); } goto parse_error; default: goto parse_error; } @@ -381,15 +384,15 @@ switch (op[0]) { case 'c': { switch (op[7]) { case 'e': - if (strcmp(op, "f32x4.ceil") == 0) { return makeUnary(s, UnaryOp::CeilVecF32x4); } + if (op == "f32x4.ceil"sv) { return makeUnary(s, UnaryOp::CeilVecF32x4); } goto parse_error; case 'o': { switch (op[20]) { case 's': - if (strcmp(op, "f32x4.convert_i32x4_s") == 0) { return makeUnary(s, UnaryOp::ConvertSVecI32x4ToVecF32x4); } + if (op == "f32x4.convert_i32x4_s"sv) { return makeUnary(s, UnaryOp::ConvertSVecI32x4ToVecF32x4); } goto parse_error; case 'u': - if (strcmp(op, "f32x4.convert_i32x4_u") == 0) { return makeUnary(s, UnaryOp::ConvertUVecI32x4ToVecF32x4); } + if (op == "f32x4.convert_i32x4_u"sv) { return makeUnary(s, UnaryOp::ConvertUVecI32x4ToVecF32x4); } goto parse_error; default: goto parse_error; } @@ -400,10 +403,10 @@ switch (op[0]) { case 'd': { switch (op[7]) { case 'e': - if (strcmp(op, "f32x4.demote_f64x2_zero") == 0) { return makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4); } + if (op == "f32x4.demote_f64x2_zero"sv) { return makeUnary(s, UnaryOp::DemoteZeroVecF64x2ToVecF32x4); } goto parse_error; case 'i': - if (strcmp(op, "f32x4.div") == 0) { return makeBinary(s, BinaryOp::DivVecF32x4); } + if (op == "f32x4.div"sv) { return makeBinary(s, BinaryOp::DivVecF32x4); } goto parse_error; default: goto parse_error; } @@ -411,24 +414,24 @@ switch (op[0]) { case 'e': { switch (op[7]) { case 'q': - if (strcmp(op, "f32x4.eq") == 0) { return makeBinary(s, BinaryOp::EqVecF32x4); } + if (op == "f32x4.eq"sv) { return makeBinary(s, BinaryOp::EqVecF32x4); } goto parse_error; case 'x': - if (strcmp(op, "f32x4.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecF32x4, 4); } + if (op == "f32x4.extract_lane"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecF32x4, 4); } goto parse_error; default: goto parse_error; } } case 'f': - if (strcmp(op, "f32x4.floor") == 0) { return makeUnary(s, UnaryOp::FloorVecF32x4); } + if (op == "f32x4.floor"sv) { return makeUnary(s, UnaryOp::FloorVecF32x4); } goto parse_error; case 'g': { switch (op[7]) { case 'e': - if (strcmp(op, "f32x4.ge") == 0) { return makeBinary(s, BinaryOp::GeVecF32x4); } + if (op == "f32x4.ge"sv) { return makeBinary(s, BinaryOp::GeVecF32x4); } goto parse_error; case 't': - if (strcmp(op, "f32x4.gt") == 0) { return makeBinary(s, BinaryOp::GtVecF32x4); } + if (op == "f32x4.gt"sv) { return makeBinary(s, BinaryOp::GtVecF32x4); } goto parse_error; default: goto parse_error; } @@ -436,10 +439,10 @@ switch (op[0]) { case 'l': { switch (op[7]) { case 'e': - if (strcmp(op, "f32x4.le") == 0) { return makeBinary(s, BinaryOp::LeVecF32x4); } + if (op == "f32x4.le"sv) { return makeBinary(s, BinaryOp::LeVecF32x4); } goto parse_error; case 't': - if (strcmp(op, "f32x4.lt") == 0) { return makeBinary(s, BinaryOp::LtVecF32x4); } + if (op == "f32x4.lt"sv) { return makeBinary(s, BinaryOp::LtVecF32x4); } goto parse_error; default: goto parse_error; } @@ -447,13 +450,13 @@ switch (op[0]) { case 'm': { switch (op[7]) { case 'a': - if (strcmp(op, "f32x4.max") == 0) { return makeBinary(s, BinaryOp::MaxVecF32x4); } + if (op == "f32x4.max"sv) { return makeBinary(s, BinaryOp::MaxVecF32x4); } goto parse_error; case 'i': - if (strcmp(op, "f32x4.min") == 0) { return makeBinary(s, BinaryOp::MinVecF32x4); } + if (op == "f32x4.min"sv) { return makeBinary(s, BinaryOp::MinVecF32x4); } goto parse_error; case 'u': - if (strcmp(op, "f32x4.mul") == 0) { return makeBinary(s, BinaryOp::MulVecF32x4); } + if (op == "f32x4.mul"sv) { return makeBinary(s, BinaryOp::MulVecF32x4); } goto parse_error; default: goto parse_error; } @@ -461,13 +464,13 @@ switch (op[0]) { case 'n': { switch (op[8]) { case '\0': - if (strcmp(op, "f32x4.ne") == 0) { return makeBinary(s, BinaryOp::NeVecF32x4); } + if (op == "f32x4.ne"sv) { return makeBinary(s, BinaryOp::NeVecF32x4); } goto parse_error; case 'a': - if (strcmp(op, "f32x4.nearest") == 0) { return makeUnary(s, UnaryOp::NearestVecF32x4); } + if (op == "f32x4.nearest"sv) { return makeUnary(s, UnaryOp::NearestVecF32x4); } goto parse_error; case 'g': - if (strcmp(op, "f32x4.neg") == 0) { return makeUnary(s, UnaryOp::NegVecF32x4); } + if (op == "f32x4.neg"sv) { return makeUnary(s, UnaryOp::NegVecF32x4); } goto parse_error; default: goto parse_error; } @@ -475,10 +478,10 @@ switch (op[0]) { case 'p': { switch (op[8]) { case 'a': - if (strcmp(op, "f32x4.pmax") == 0) { return makeBinary(s, BinaryOp::PMaxVecF32x4); } + if (op == "f32x4.pmax"sv) { return makeBinary(s, BinaryOp::PMaxVecF32x4); } goto parse_error; case 'i': - if (strcmp(op, "f32x4.pmin") == 0) { return makeBinary(s, BinaryOp::PMinVecF32x4); } + if (op == "f32x4.pmin"sv) { return makeBinary(s, BinaryOp::PMinVecF32x4); } goto parse_error; default: goto parse_error; } @@ -490,10 +493,10 @@ switch (op[0]) { case 'f': { switch (op[16]) { case 'a': - if (strcmp(op, "f32x4.relaxed_fma") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF32x4); } + if (op == "f32x4.relaxed_fma"sv) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF32x4); } goto parse_error; case 's': - if (strcmp(op, "f32x4.relaxed_fms") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF32x4); } + if (op == "f32x4.relaxed_fms"sv) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF32x4); } goto parse_error; default: goto parse_error; } @@ -501,10 +504,10 @@ switch (op[0]) { case 'm': { switch (op[15]) { case 'a': - if (strcmp(op, "f32x4.relaxed_max") == 0) { return makeBinary(s, BinaryOp::RelaxedMaxVecF32x4); } + if (op == "f32x4.relaxed_max"sv) { return makeBinary(s, BinaryOp::RelaxedMaxVecF32x4); } goto parse_error; case 'i': - if (strcmp(op, "f32x4.relaxed_min") == 0) { return makeBinary(s, BinaryOp::RelaxedMinVecF32x4); } + if (op == "f32x4.relaxed_min"sv) { return makeBinary(s, BinaryOp::RelaxedMinVecF32x4); } goto parse_error; default: goto parse_error; } @@ -513,7 +516,7 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "f32x4.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF32x4, 4); } + if (op == "f32x4.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF32x4, 4); } goto parse_error; default: goto parse_error; } @@ -521,19 +524,19 @@ switch (op[0]) { case 's': { switch (op[7]) { case 'p': - if (strcmp(op, "f32x4.splat") == 0) { return makeUnary(s, UnaryOp::SplatVecF32x4); } + if (op == "f32x4.splat"sv) { return makeUnary(s, UnaryOp::SplatVecF32x4); } goto parse_error; case 'q': - if (strcmp(op, "f32x4.sqrt") == 0) { return makeUnary(s, UnaryOp::SqrtVecF32x4); } + if (op == "f32x4.sqrt"sv) { return makeUnary(s, UnaryOp::SqrtVecF32x4); } goto parse_error; case 'u': - if (strcmp(op, "f32x4.sub") == 0) { return makeBinary(s, BinaryOp::SubVecF32x4); } + if (op == "f32x4.sub"sv) { return makeBinary(s, BinaryOp::SubVecF32x4); } goto parse_error; default: goto parse_error; } } case 't': - if (strcmp(op, "f32x4.trunc") == 0) { return makeUnary(s, UnaryOp::TruncVecF32x4); } + if (op == "f32x4.trunc"sv) { return makeUnary(s, UnaryOp::TruncVecF32x4); } goto parse_error; default: goto parse_error; } @@ -548,10 +551,10 @@ switch (op[0]) { case 'a': { switch (op[5]) { case 'b': - if (strcmp(op, "f64.abs") == 0) { return makeUnary(s, UnaryOp::AbsFloat64); } + if (op == "f64.abs"sv) { return makeUnary(s, UnaryOp::AbsFloat64); } goto parse_error; case 'd': - if (strcmp(op, "f64.add") == 0) { return makeBinary(s, BinaryOp::AddFloat64); } + if (op == "f64.add"sv) { return makeBinary(s, BinaryOp::AddFloat64); } goto parse_error; default: goto parse_error; } @@ -559,24 +562,24 @@ switch (op[0]) { case 'c': { switch (op[5]) { case 'e': - if (strcmp(op, "f64.ceil") == 0) { return makeUnary(s, UnaryOp::CeilFloat64); } + if (op == "f64.ceil"sv) { return makeUnary(s, UnaryOp::CeilFloat64); } goto parse_error; case 'o': { switch (op[6]) { case 'n': { switch (op[7]) { case 's': - if (strcmp(op, "f64.const") == 0) { return makeConst(s, Type::f64); } + if (op == "f64.const"sv) { return makeConst(s, Type::f64); } goto parse_error; case 'v': { switch (op[13]) { case '3': { switch (op[16]) { case 's': - if (strcmp(op, "f64.convert_i32_s") == 0) { return makeUnary(s, UnaryOp::ConvertSInt32ToFloat64); } + if (op == "f64.convert_i32_s"sv) { return makeUnary(s, UnaryOp::ConvertSInt32ToFloat64); } goto parse_error; case 'u': - if (strcmp(op, "f64.convert_i32_u") == 0) { return makeUnary(s, UnaryOp::ConvertUInt32ToFloat64); } + if (op == "f64.convert_i32_u"sv) { return makeUnary(s, UnaryOp::ConvertUInt32ToFloat64); } goto parse_error; default: goto parse_error; } @@ -584,10 +587,10 @@ switch (op[0]) { case '6': { switch (op[16]) { case 's': - if (strcmp(op, "f64.convert_i64_s") == 0) { return makeUnary(s, UnaryOp::ConvertSInt64ToFloat64); } + if (op == "f64.convert_i64_s"sv) { return makeUnary(s, UnaryOp::ConvertSInt64ToFloat64); } goto parse_error; case 'u': - if (strcmp(op, "f64.convert_i64_u") == 0) { return makeUnary(s, UnaryOp::ConvertUInt64ToFloat64); } + if (op == "f64.convert_i64_u"sv) { return makeUnary(s, UnaryOp::ConvertUInt64ToFloat64); } goto parse_error; default: goto parse_error; } @@ -599,7 +602,7 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "f64.copysign") == 0) { return makeBinary(s, BinaryOp::CopySignFloat64); } + if (op == "f64.copysign"sv) { return makeBinary(s, BinaryOp::CopySignFloat64); } goto parse_error; default: goto parse_error; } @@ -608,21 +611,21 @@ switch (op[0]) { } } case 'd': - if (strcmp(op, "f64.div") == 0) { return makeBinary(s, BinaryOp::DivFloat64); } + if (op == "f64.div"sv) { return makeBinary(s, BinaryOp::DivFloat64); } goto parse_error; case 'e': - if (strcmp(op, "f64.eq") == 0) { return makeBinary(s, BinaryOp::EqFloat64); } + if (op == "f64.eq"sv) { return makeBinary(s, BinaryOp::EqFloat64); } goto parse_error; case 'f': - if (strcmp(op, "f64.floor") == 0) { return makeUnary(s, UnaryOp::FloorFloat64); } + if (op == "f64.floor"sv) { return makeUnary(s, UnaryOp::FloorFloat64); } goto parse_error; case 'g': { switch (op[5]) { case 'e': - if (strcmp(op, "f64.ge") == 0) { return makeBinary(s, BinaryOp::GeFloat64); } + if (op == "f64.ge"sv) { return makeBinary(s, BinaryOp::GeFloat64); } goto parse_error; case 't': - if (strcmp(op, "f64.gt") == 0) { return makeBinary(s, BinaryOp::GtFloat64); } + if (op == "f64.gt"sv) { return makeBinary(s, BinaryOp::GtFloat64); } goto parse_error; default: goto parse_error; } @@ -630,13 +633,13 @@ switch (op[0]) { case 'l': { switch (op[5]) { case 'e': - if (strcmp(op, "f64.le") == 0) { return makeBinary(s, BinaryOp::LeFloat64); } + if (op == "f64.le"sv) { return makeBinary(s, BinaryOp::LeFloat64); } goto parse_error; case 'o': - if (strcmp(op, "f64.load") == 0) { return makeLoad(s, Type::f64, /*isAtomic=*/false); } + if (op == "f64.load"sv) { return makeLoad(s, Type::f64, /*isAtomic=*/false); } goto parse_error; case 't': - if (strcmp(op, "f64.lt") == 0) { return makeBinary(s, BinaryOp::LtFloat64); } + if (op == "f64.lt"sv) { return makeBinary(s, BinaryOp::LtFloat64); } goto parse_error; default: goto parse_error; } @@ -644,13 +647,13 @@ switch (op[0]) { case 'm': { switch (op[5]) { case 'a': - if (strcmp(op, "f64.max") == 0) { return makeBinary(s, BinaryOp::MaxFloat64); } + if (op == "f64.max"sv) { return makeBinary(s, BinaryOp::MaxFloat64); } goto parse_error; case 'i': - if (strcmp(op, "f64.min") == 0) { return makeBinary(s, BinaryOp::MinFloat64); } + if (op == "f64.min"sv) { return makeBinary(s, BinaryOp::MinFloat64); } goto parse_error; case 'u': - if (strcmp(op, "f64.mul") == 0) { return makeBinary(s, BinaryOp::MulFloat64); } + if (op == "f64.mul"sv) { return makeBinary(s, BinaryOp::MulFloat64); } goto parse_error; default: goto parse_error; } @@ -658,39 +661,39 @@ switch (op[0]) { case 'n': { switch (op[6]) { case '\0': - if (strcmp(op, "f64.ne") == 0) { return makeBinary(s, BinaryOp::NeFloat64); } + if (op == "f64.ne"sv) { return makeBinary(s, BinaryOp::NeFloat64); } goto parse_error; case 'a': - if (strcmp(op, "f64.nearest") == 0) { return makeUnary(s, UnaryOp::NearestFloat64); } + if (op == "f64.nearest"sv) { return makeUnary(s, UnaryOp::NearestFloat64); } goto parse_error; case 'g': - if (strcmp(op, "f64.neg") == 0) { return makeUnary(s, UnaryOp::NegFloat64); } + if (op == "f64.neg"sv) { return makeUnary(s, UnaryOp::NegFloat64); } goto parse_error; default: goto parse_error; } } case 'p': - if (strcmp(op, "f64.promote_f32") == 0) { return makeUnary(s, UnaryOp::PromoteFloat32); } + if (op == "f64.promote_f32"sv) { return makeUnary(s, UnaryOp::PromoteFloat32); } goto parse_error; case 'r': - if (strcmp(op, "f64.reinterpret_i64") == 0) { return makeUnary(s, UnaryOp::ReinterpretInt64); } + if (op == "f64.reinterpret_i64"sv) { return makeUnary(s, UnaryOp::ReinterpretInt64); } goto parse_error; case 's': { switch (op[5]) { case 'q': - if (strcmp(op, "f64.sqrt") == 0) { return makeUnary(s, UnaryOp::SqrtFloat64); } + if (op == "f64.sqrt"sv) { return makeUnary(s, UnaryOp::SqrtFloat64); } goto parse_error; case 't': - if (strcmp(op, "f64.store") == 0) { return makeStore(s, Type::f64, /*isAtomic=*/false); } + if (op == "f64.store"sv) { return makeStore(s, Type::f64, /*isAtomic=*/false); } goto parse_error; case 'u': - if (strcmp(op, "f64.sub") == 0) { return makeBinary(s, BinaryOp::SubFloat64); } + if (op == "f64.sub"sv) { return makeBinary(s, BinaryOp::SubFloat64); } goto parse_error; default: goto parse_error; } } case 't': - if (strcmp(op, "f64.trunc") == 0) { return makeUnary(s, UnaryOp::TruncFloat64); } + if (op == "f64.trunc"sv) { return makeUnary(s, UnaryOp::TruncFloat64); } goto parse_error; default: goto parse_error; } @@ -700,10 +703,10 @@ switch (op[0]) { case 'a': { switch (op[7]) { case 'b': - if (strcmp(op, "f64x2.abs") == 0) { return makeUnary(s, UnaryOp::AbsVecF64x2); } + if (op == "f64x2.abs"sv) { return makeUnary(s, UnaryOp::AbsVecF64x2); } goto parse_error; case 'd': - if (strcmp(op, "f64x2.add") == 0) { return makeBinary(s, BinaryOp::AddVecF64x2); } + if (op == "f64x2.add"sv) { return makeBinary(s, BinaryOp::AddVecF64x2); } goto parse_error; default: goto parse_error; } @@ -711,15 +714,15 @@ switch (op[0]) { case 'c': { switch (op[7]) { case 'e': - if (strcmp(op, "f64x2.ceil") == 0) { return makeUnary(s, UnaryOp::CeilVecF64x2); } + if (op == "f64x2.ceil"sv) { return makeUnary(s, UnaryOp::CeilVecF64x2); } goto parse_error; case 'o': { switch (op[24]) { case 's': - if (strcmp(op, "f64x2.convert_low_i32x4_s") == 0) { return makeUnary(s, UnaryOp::ConvertLowSVecI32x4ToVecF64x2); } + if (op == "f64x2.convert_low_i32x4_s"sv) { return makeUnary(s, UnaryOp::ConvertLowSVecI32x4ToVecF64x2); } goto parse_error; case 'u': - if (strcmp(op, "f64x2.convert_low_i32x4_u") == 0) { return makeUnary(s, UnaryOp::ConvertLowUVecI32x4ToVecF64x2); } + if (op == "f64x2.convert_low_i32x4_u"sv) { return makeUnary(s, UnaryOp::ConvertLowUVecI32x4ToVecF64x2); } goto parse_error; default: goto parse_error; } @@ -728,29 +731,29 @@ switch (op[0]) { } } case 'd': - if (strcmp(op, "f64x2.div") == 0) { return makeBinary(s, BinaryOp::DivVecF64x2); } + if (op == "f64x2.div"sv) { return makeBinary(s, BinaryOp::DivVecF64x2); } goto parse_error; case 'e': { switch (op[7]) { case 'q': - if (strcmp(op, "f64x2.eq") == 0) { return makeBinary(s, BinaryOp::EqVecF64x2); } + if (op == "f64x2.eq"sv) { return makeBinary(s, BinaryOp::EqVecF64x2); } goto parse_error; case 'x': - if (strcmp(op, "f64x2.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecF64x2, 2); } + if (op == "f64x2.extract_lane"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecF64x2, 2); } goto parse_error; default: goto parse_error; } } case 'f': - if (strcmp(op, "f64x2.floor") == 0) { return makeUnary(s, UnaryOp::FloorVecF64x2); } + if (op == "f64x2.floor"sv) { return makeUnary(s, UnaryOp::FloorVecF64x2); } goto parse_error; case 'g': { switch (op[7]) { case 'e': - if (strcmp(op, "f64x2.ge") == 0) { return makeBinary(s, BinaryOp::GeVecF64x2); } + if (op == "f64x2.ge"sv) { return makeBinary(s, BinaryOp::GeVecF64x2); } goto parse_error; case 't': - if (strcmp(op, "f64x2.gt") == 0) { return makeBinary(s, BinaryOp::GtVecF64x2); } + if (op == "f64x2.gt"sv) { return makeBinary(s, BinaryOp::GtVecF64x2); } goto parse_error; default: goto parse_error; } @@ -758,10 +761,10 @@ switch (op[0]) { case 'l': { switch (op[7]) { case 'e': - if (strcmp(op, "f64x2.le") == 0) { return makeBinary(s, BinaryOp::LeVecF64x2); } + if (op == "f64x2.le"sv) { return makeBinary(s, BinaryOp::LeVecF64x2); } goto parse_error; case 't': - if (strcmp(op, "f64x2.lt") == 0) { return makeBinary(s, BinaryOp::LtVecF64x2); } + if (op == "f64x2.lt"sv) { return makeBinary(s, BinaryOp::LtVecF64x2); } goto parse_error; default: goto parse_error; } @@ -769,13 +772,13 @@ switch (op[0]) { case 'm': { switch (op[7]) { case 'a': - if (strcmp(op, "f64x2.max") == 0) { return makeBinary(s, BinaryOp::MaxVecF64x2); } + if (op == "f64x2.max"sv) { return makeBinary(s, BinaryOp::MaxVecF64x2); } goto parse_error; case 'i': - if (strcmp(op, "f64x2.min") == 0) { return makeBinary(s, BinaryOp::MinVecF64x2); } + if (op == "f64x2.min"sv) { return makeBinary(s, BinaryOp::MinVecF64x2); } goto parse_error; case 'u': - if (strcmp(op, "f64x2.mul") == 0) { return makeBinary(s, BinaryOp::MulVecF64x2); } + if (op == "f64x2.mul"sv) { return makeBinary(s, BinaryOp::MulVecF64x2); } goto parse_error; default: goto parse_error; } @@ -783,13 +786,13 @@ switch (op[0]) { case 'n': { switch (op[8]) { case '\0': - if (strcmp(op, "f64x2.ne") == 0) { return makeBinary(s, BinaryOp::NeVecF64x2); } + if (op == "f64x2.ne"sv) { return makeBinary(s, BinaryOp::NeVecF64x2); } goto parse_error; case 'a': - if (strcmp(op, "f64x2.nearest") == 0) { return makeUnary(s, UnaryOp::NearestVecF64x2); } + if (op == "f64x2.nearest"sv) { return makeUnary(s, UnaryOp::NearestVecF64x2); } goto parse_error; case 'g': - if (strcmp(op, "f64x2.neg") == 0) { return makeUnary(s, UnaryOp::NegVecF64x2); } + if (op == "f64x2.neg"sv) { return makeUnary(s, UnaryOp::NegVecF64x2); } goto parse_error; default: goto parse_error; } @@ -799,16 +802,16 @@ switch (op[0]) { case 'm': { switch (op[8]) { case 'a': - if (strcmp(op, "f64x2.pmax") == 0) { return makeBinary(s, BinaryOp::PMaxVecF64x2); } + if (op == "f64x2.pmax"sv) { return makeBinary(s, BinaryOp::PMaxVecF64x2); } goto parse_error; case 'i': - if (strcmp(op, "f64x2.pmin") == 0) { return makeBinary(s, BinaryOp::PMinVecF64x2); } + if (op == "f64x2.pmin"sv) { return makeBinary(s, BinaryOp::PMinVecF64x2); } goto parse_error; default: goto parse_error; } } case 'r': - if (strcmp(op, "f64x2.promote_low_f32x4") == 0) { return makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2); } + if (op == "f64x2.promote_low_f32x4"sv) { return makeUnary(s, UnaryOp::PromoteLowVecF32x4ToVecF64x2); } goto parse_error; default: goto parse_error; } @@ -820,10 +823,10 @@ switch (op[0]) { case 'f': { switch (op[16]) { case 'a': - if (strcmp(op, "f64x2.relaxed_fma") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF64x2); } + if (op == "f64x2.relaxed_fma"sv) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmaVecF64x2); } goto parse_error; case 's': - if (strcmp(op, "f64x2.relaxed_fms") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF64x2); } + if (op == "f64x2.relaxed_fms"sv) { return makeSIMDTernary(s, SIMDTernaryOp::RelaxedFmsVecF64x2); } goto parse_error; default: goto parse_error; } @@ -831,10 +834,10 @@ switch (op[0]) { case 'm': { switch (op[15]) { case 'a': - if (strcmp(op, "f64x2.relaxed_max") == 0) { return makeBinary(s, BinaryOp::RelaxedMaxVecF64x2); } + if (op == "f64x2.relaxed_max"sv) { return makeBinary(s, BinaryOp::RelaxedMaxVecF64x2); } goto parse_error; case 'i': - if (strcmp(op, "f64x2.relaxed_min") == 0) { return makeBinary(s, BinaryOp::RelaxedMinVecF64x2); } + if (op == "f64x2.relaxed_min"sv) { return makeBinary(s, BinaryOp::RelaxedMinVecF64x2); } goto parse_error; default: goto parse_error; } @@ -843,7 +846,7 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "f64x2.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF64x2, 2); } + if (op == "f64x2.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecF64x2, 2); } goto parse_error; default: goto parse_error; } @@ -851,19 +854,19 @@ switch (op[0]) { case 's': { switch (op[7]) { case 'p': - if (strcmp(op, "f64x2.splat") == 0) { return makeUnary(s, UnaryOp::SplatVecF64x2); } + if (op == "f64x2.splat"sv) { return makeUnary(s, UnaryOp::SplatVecF64x2); } goto parse_error; case 'q': - if (strcmp(op, "f64x2.sqrt") == 0) { return makeUnary(s, UnaryOp::SqrtVecF64x2); } + if (op == "f64x2.sqrt"sv) { return makeUnary(s, UnaryOp::SqrtVecF64x2); } goto parse_error; case 'u': - if (strcmp(op, "f64x2.sub") == 0) { return makeBinary(s, BinaryOp::SubVecF64x2); } + if (op == "f64x2.sub"sv) { return makeBinary(s, BinaryOp::SubVecF64x2); } goto parse_error; default: goto parse_error; } } case 't': - if (strcmp(op, "f64x2.trunc") == 0) { return makeUnary(s, UnaryOp::TruncVecF64x2); } + if (op == "f64x2.trunc"sv) { return makeUnary(s, UnaryOp::TruncVecF64x2); } goto parse_error; default: goto parse_error; } @@ -877,10 +880,10 @@ switch (op[0]) { case 'g': { switch (op[7]) { case 'g': - if (strcmp(op, "global.get") == 0) { return makeGlobalGet(s); } + if (op == "global.get"sv) { return makeGlobalGet(s); } goto parse_error; case 's': - if (strcmp(op, "global.set") == 0) { return makeGlobalSet(s); } + if (op == "global.set"sv) { return makeGlobalSet(s); } goto parse_error; default: goto parse_error; } @@ -892,20 +895,20 @@ switch (op[0]) { case 'a': { switch (op[7]) { case 'b': - if (strcmp(op, "i16x8.abs") == 0) { return makeUnary(s, UnaryOp::AbsVecI16x8); } + if (op == "i16x8.abs"sv) { return makeUnary(s, UnaryOp::AbsVecI16x8); } goto parse_error; case 'd': { switch (op[9]) { case '\0': - if (strcmp(op, "i16x8.add") == 0) { return makeBinary(s, BinaryOp::AddVecI16x8); } + if (op == "i16x8.add"sv) { return makeBinary(s, BinaryOp::AddVecI16x8); } goto parse_error; case '_': { switch (op[14]) { case 's': - if (strcmp(op, "i16x8.add_sat_s") == 0) { return makeBinary(s, BinaryOp::AddSatSVecI16x8); } + if (op == "i16x8.add_sat_s"sv) { return makeBinary(s, BinaryOp::AddSatSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.add_sat_u") == 0) { return makeBinary(s, BinaryOp::AddSatUVecI16x8); } + if (op == "i16x8.add_sat_u"sv) { return makeBinary(s, BinaryOp::AddSatUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -914,34 +917,34 @@ switch (op[0]) { } } case 'l': - if (strcmp(op, "i16x8.all_true") == 0) { return makeUnary(s, UnaryOp::AllTrueVecI16x8); } + if (op == "i16x8.all_true"sv) { return makeUnary(s, UnaryOp::AllTrueVecI16x8); } goto parse_error; case 'v': - if (strcmp(op, "i16x8.avgr_u") == 0) { return makeBinary(s, BinaryOp::AvgrUVecI16x8); } + if (op == "i16x8.avgr_u"sv) { return makeBinary(s, BinaryOp::AvgrUVecI16x8); } goto parse_error; default: goto parse_error; } } case 'b': - if (strcmp(op, "i16x8.bitmask") == 0) { return makeUnary(s, UnaryOp::BitmaskVecI16x8); } + if (op == "i16x8.bitmask"sv) { return makeUnary(s, UnaryOp::BitmaskVecI16x8); } goto parse_error; case 'd': - if (strcmp(op, "i16x8.dot_i8x16_i7x16_s") == 0) { return makeBinary(s, BinaryOp::DotI8x16I7x16SToVecI16x8); } + if (op == "i16x8.dot_i8x16_i7x16_s"sv) { return makeBinary(s, BinaryOp::DotI8x16I7x16SToVecI16x8); } goto parse_error; case 'e': { switch (op[7]) { case 'q': - if (strcmp(op, "i16x8.eq") == 0) { return makeBinary(s, BinaryOp::EqVecI16x8); } + if (op == "i16x8.eq"sv) { return makeBinary(s, BinaryOp::EqVecI16x8); } goto parse_error; case 'x': { switch (op[9]) { case 'a': { switch (op[28]) { case 's': - if (strcmp(op, "i16x8.extadd_pairwise_i8x16_s") == 0) { return makeUnary(s, UnaryOp::ExtAddPairwiseSVecI8x16ToI16x8); } + if (op == "i16x8.extadd_pairwise_i8x16_s"sv) { return makeUnary(s, UnaryOp::ExtAddPairwiseSVecI8x16ToI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.extadd_pairwise_i8x16_u") == 0) { return makeUnary(s, UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8); } + if (op == "i16x8.extadd_pairwise_i8x16_u"sv) { return makeUnary(s, UnaryOp::ExtAddPairwiseUVecI8x16ToI16x8); } goto parse_error; default: goto parse_error; } @@ -951,10 +954,10 @@ switch (op[0]) { case 'h': { switch (op[24]) { case 's': - if (strcmp(op, "i16x8.extend_high_i8x16_s") == 0) { return makeUnary(s, UnaryOp::ExtendHighSVecI8x16ToVecI16x8); } + if (op == "i16x8.extend_high_i8x16_s"sv) { return makeUnary(s, UnaryOp::ExtendHighSVecI8x16ToVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.extend_high_i8x16_u") == 0) { return makeUnary(s, UnaryOp::ExtendHighUVecI8x16ToVecI16x8); } + if (op == "i16x8.extend_high_i8x16_u"sv) { return makeUnary(s, UnaryOp::ExtendHighUVecI8x16ToVecI16x8); } goto parse_error; default: goto parse_error; } @@ -962,10 +965,10 @@ switch (op[0]) { case 'l': { switch (op[23]) { case 's': - if (strcmp(op, "i16x8.extend_low_i8x16_s") == 0) { return makeUnary(s, UnaryOp::ExtendLowSVecI8x16ToVecI16x8); } + if (op == "i16x8.extend_low_i8x16_s"sv) { return makeUnary(s, UnaryOp::ExtendLowSVecI8x16ToVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.extend_low_i8x16_u") == 0) { return makeUnary(s, UnaryOp::ExtendLowUVecI8x16ToVecI16x8); } + if (op == "i16x8.extend_low_i8x16_u"sv) { return makeUnary(s, UnaryOp::ExtendLowUVecI8x16ToVecI16x8); } goto parse_error; default: goto parse_error; } @@ -978,10 +981,10 @@ switch (op[0]) { case 'h': { switch (op[24]) { case 's': - if (strcmp(op, "i16x8.extmul_high_i8x16_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI16x8); } + if (op == "i16x8.extmul_high_i8x16_s"sv) { return makeBinary(s, BinaryOp::ExtMulHighSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.extmul_high_i8x16_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI16x8); } + if (op == "i16x8.extmul_high_i8x16_u"sv) { return makeBinary(s, BinaryOp::ExtMulHighUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -989,10 +992,10 @@ switch (op[0]) { case 'l': { switch (op[23]) { case 's': - if (strcmp(op, "i16x8.extmul_low_i8x16_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI16x8); } + if (op == "i16x8.extmul_low_i8x16_s"sv) { return makeBinary(s, BinaryOp::ExtMulLowSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.extmul_low_i8x16_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI16x8); } + if (op == "i16x8.extmul_low_i8x16_u"sv) { return makeBinary(s, BinaryOp::ExtMulLowUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1003,10 +1006,10 @@ switch (op[0]) { case 'r': { switch (op[19]) { case 's': - if (strcmp(op, "i16x8.extract_lane_s") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI16x8, 8); } + if (op == "i16x8.extract_lane_s"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI16x8, 8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.extract_lane_u") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI16x8, 8); } + if (op == "i16x8.extract_lane_u"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI16x8, 8); } goto parse_error; default: goto parse_error; } @@ -1022,10 +1025,10 @@ switch (op[0]) { case 'e': { switch (op[9]) { case 's': - if (strcmp(op, "i16x8.ge_s") == 0) { return makeBinary(s, BinaryOp::GeSVecI16x8); } + if (op == "i16x8.ge_s"sv) { return makeBinary(s, BinaryOp::GeSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.ge_u") == 0) { return makeBinary(s, BinaryOp::GeUVecI16x8); } + if (op == "i16x8.ge_u"sv) { return makeBinary(s, BinaryOp::GeUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1033,10 +1036,10 @@ switch (op[0]) { case 't': { switch (op[9]) { case 's': - if (strcmp(op, "i16x8.gt_s") == 0) { return makeBinary(s, BinaryOp::GtSVecI16x8); } + if (op == "i16x8.gt_s"sv) { return makeBinary(s, BinaryOp::GtSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.gt_u") == 0) { return makeBinary(s, BinaryOp::GtUVecI16x8); } + if (op == "i16x8.gt_u"sv) { return makeBinary(s, BinaryOp::GtUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1047,15 +1050,15 @@ switch (op[0]) { case 'l': { switch (op[7]) { case 'a': - if (strcmp(op, "i16x8.laneselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI16x8); } + if (op == "i16x8.laneselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI16x8); } goto parse_error; case 'e': { switch (op[9]) { case 's': - if (strcmp(op, "i16x8.le_s") == 0) { return makeBinary(s, BinaryOp::LeSVecI16x8); } + if (op == "i16x8.le_s"sv) { return makeBinary(s, BinaryOp::LeSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.le_u") == 0) { return makeBinary(s, BinaryOp::LeUVecI16x8); } + if (op == "i16x8.le_u"sv) { return makeBinary(s, BinaryOp::LeUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1063,10 +1066,10 @@ switch (op[0]) { case 't': { switch (op[9]) { case 's': - if (strcmp(op, "i16x8.lt_s") == 0) { return makeBinary(s, BinaryOp::LtSVecI16x8); } + if (op == "i16x8.lt_s"sv) { return makeBinary(s, BinaryOp::LtSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.lt_u") == 0) { return makeBinary(s, BinaryOp::LtUVecI16x8); } + if (op == "i16x8.lt_u"sv) { return makeBinary(s, BinaryOp::LtUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1079,10 +1082,10 @@ switch (op[0]) { case 'a': { switch (op[10]) { case 's': - if (strcmp(op, "i16x8.max_s") == 0) { return makeBinary(s, BinaryOp::MaxSVecI16x8); } + if (op == "i16x8.max_s"sv) { return makeBinary(s, BinaryOp::MaxSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.max_u") == 0) { return makeBinary(s, BinaryOp::MaxUVecI16x8); } + if (op == "i16x8.max_u"sv) { return makeBinary(s, BinaryOp::MaxUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1090,16 +1093,16 @@ switch (op[0]) { case 'i': { switch (op[10]) { case 's': - if (strcmp(op, "i16x8.min_s") == 0) { return makeBinary(s, BinaryOp::MinSVecI16x8); } + if (op == "i16x8.min_s"sv) { return makeBinary(s, BinaryOp::MinSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.min_u") == 0) { return makeBinary(s, BinaryOp::MinUVecI16x8); } + if (op == "i16x8.min_u"sv) { return makeBinary(s, BinaryOp::MinUVecI16x8); } goto parse_error; default: goto parse_error; } } case 'u': - if (strcmp(op, "i16x8.mul") == 0) { return makeBinary(s, BinaryOp::MulVecI16x8); } + if (op == "i16x8.mul"sv) { return makeBinary(s, BinaryOp::MulVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1109,10 +1112,10 @@ switch (op[0]) { case 'a': { switch (op[19]) { case 's': - if (strcmp(op, "i16x8.narrow_i32x4_s") == 0) { return makeBinary(s, BinaryOp::NarrowSVecI32x4ToVecI16x8); } + if (op == "i16x8.narrow_i32x4_s"sv) { return makeBinary(s, BinaryOp::NarrowSVecI32x4ToVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.narrow_i32x4_u") == 0) { return makeBinary(s, BinaryOp::NarrowUVecI32x4ToVecI16x8); } + if (op == "i16x8.narrow_i32x4_u"sv) { return makeBinary(s, BinaryOp::NarrowUVecI32x4ToVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1120,10 +1123,10 @@ switch (op[0]) { case 'e': { switch (op[8]) { case '\0': - if (strcmp(op, "i16x8.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI16x8); } + if (op == "i16x8.ne"sv) { return makeBinary(s, BinaryOp::NeVecI16x8); } goto parse_error; case 'g': - if (strcmp(op, "i16x8.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI16x8); } + if (op == "i16x8.neg"sv) { return makeUnary(s, UnaryOp::NegVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1132,15 +1135,15 @@ switch (op[0]) { } } case 'q': - if (strcmp(op, "i16x8.q15mulr_sat_s") == 0) { return makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8); } + if (op == "i16x8.q15mulr_sat_s"sv) { return makeBinary(s, BinaryOp::Q15MulrSatSVecI16x8); } goto parse_error; case 'r': { switch (op[8]) { case 'l': - if (strcmp(op, "i16x8.relaxed_q15mulr_s") == 0) { return makeBinary(s, BinaryOp::RelaxedQ15MulrSVecI16x8); } + if (op == "i16x8.relaxed_q15mulr_s"sv) { return makeBinary(s, BinaryOp::RelaxedQ15MulrSVecI16x8); } goto parse_error; case 'p': - if (strcmp(op, "i16x8.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI16x8, 8); } + if (op == "i16x8.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI16x8, 8); } goto parse_error; default: goto parse_error; } @@ -1150,15 +1153,15 @@ switch (op[0]) { case 'h': { switch (op[8]) { case 'l': - if (strcmp(op, "i16x8.shl") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI16x8); } + if (op == "i16x8.shl"sv) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI16x8); } goto parse_error; case 'r': { switch (op[10]) { case 's': - if (strcmp(op, "i16x8.shr_s") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI16x8); } + if (op == "i16x8.shr_s"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.shr_u") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI16x8); } + if (op == "i16x8.shr_u"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1167,20 +1170,20 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "i16x8.splat") == 0) { return makeUnary(s, UnaryOp::SplatVecI16x8); } + if (op == "i16x8.splat"sv) { return makeUnary(s, UnaryOp::SplatVecI16x8); } goto parse_error; case 'u': { switch (op[9]) { case '\0': - if (strcmp(op, "i16x8.sub") == 0) { return makeBinary(s, BinaryOp::SubVecI16x8); } + if (op == "i16x8.sub"sv) { return makeBinary(s, BinaryOp::SubVecI16x8); } goto parse_error; case '_': { switch (op[14]) { case 's': - if (strcmp(op, "i16x8.sub_sat_s") == 0) { return makeBinary(s, BinaryOp::SubSatSVecI16x8); } + if (op == "i16x8.sub_sat_s"sv) { return makeBinary(s, BinaryOp::SubSatSVecI16x8); } goto parse_error; case 'u': - if (strcmp(op, "i16x8.sub_sat_u") == 0) { return makeBinary(s, BinaryOp::SubSatUVecI16x8); } + if (op == "i16x8.sub_sat_u"sv) { return makeBinary(s, BinaryOp::SubSatUVecI16x8); } goto parse_error; default: goto parse_error; } @@ -1201,16 +1204,16 @@ switch (op[0]) { case 'g': { switch (op[8]) { case 's': - if (strcmp(op, "i31.get_s") == 0) { return makeI31Get(s, true); } + if (op == "i31.get_s"sv) { return makeI31Get(s, true); } goto parse_error; case 'u': - if (strcmp(op, "i31.get_u") == 0) { return makeI31Get(s, false); } + if (op == "i31.get_u"sv) { return makeI31Get(s, false); } goto parse_error; default: goto parse_error; } } case 'n': - if (strcmp(op, "i31.new") == 0) { return makeI31New(s); } + if (op == "i31.new"sv) { return makeI31New(s); } goto parse_error; default: goto parse_error; } @@ -1222,23 +1225,23 @@ switch (op[0]) { case 'a': { switch (op[5]) { case 'd': - if (strcmp(op, "i32.add") == 0) { return makeBinary(s, BinaryOp::AddInt32); } + if (op == "i32.add"sv) { return makeBinary(s, BinaryOp::AddInt32); } goto parse_error; case 'n': - if (strcmp(op, "i32.and") == 0) { return makeBinary(s, BinaryOp::AndInt32); } + if (op == "i32.and"sv) { return makeBinary(s, BinaryOp::AndInt32); } goto parse_error; case 't': { switch (op[11]) { case 'l': { switch (op[15]) { case '\0': - if (strcmp(op, "i32.atomic.load") == 0) { return makeLoad(s, Type::i32, /*isAtomic=*/true); } + if (op == "i32.atomic.load"sv) { return makeLoad(s, Type::i32, /*isAtomic=*/true); } goto parse_error; case '1': - if (strcmp(op, "i32.atomic.load16_u") == 0) { return makeLoad(s, Type::i32, /*isAtomic=*/true); } + if (op == "i32.atomic.load16_u"sv) { return makeLoad(s, Type::i32, /*isAtomic=*/true); } goto parse_error; case '8': - if (strcmp(op, "i32.atomic.load8_u") == 0) { return makeLoad(s, Type::i32, /*isAtomic=*/true); } + if (op == "i32.atomic.load8_u"sv) { return makeLoad(s, Type::i32, /*isAtomic=*/true); } goto parse_error; default: goto parse_error; } @@ -1250,30 +1253,30 @@ switch (op[0]) { case 'a': { switch (op[16]) { case 'd': - if (strcmp(op, "i32.atomic.rmw.add") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw.add"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'n': - if (strcmp(op, "i32.atomic.rmw.and") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw.and"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; default: goto parse_error; } } case 'c': - if (strcmp(op, "i32.atomic.rmw.cmpxchg") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw.cmpxchg"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'o': - if (strcmp(op, "i32.atomic.rmw.or") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw.or"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 's': - if (strcmp(op, "i32.atomic.rmw.sub") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw.sub"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'x': { switch (op[16]) { case 'c': - if (strcmp(op, "i32.atomic.rmw.xchg") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw.xchg"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'o': - if (strcmp(op, "i32.atomic.rmw.xor") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw.xor"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; default: goto parse_error; } @@ -1286,30 +1289,30 @@ switch (op[0]) { case 'a': { switch (op[18]) { case 'd': - if (strcmp(op, "i32.atomic.rmw16.add_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw16.add_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'n': - if (strcmp(op, "i32.atomic.rmw16.and_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw16.and_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; default: goto parse_error; } } case 'c': - if (strcmp(op, "i32.atomic.rmw16.cmpxchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw16.cmpxchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'o': - if (strcmp(op, "i32.atomic.rmw16.or_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw16.or_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 's': - if (strcmp(op, "i32.atomic.rmw16.sub_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw16.sub_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'x': { switch (op[18]) { case 'c': - if (strcmp(op, "i32.atomic.rmw16.xchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw16.xchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'o': - if (strcmp(op, "i32.atomic.rmw16.xor_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw16.xor_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; default: goto parse_error; } @@ -1322,30 +1325,30 @@ switch (op[0]) { case 'a': { switch (op[17]) { case 'd': - if (strcmp(op, "i32.atomic.rmw8.add_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw8.add_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'n': - if (strcmp(op, "i32.atomic.rmw8.and_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw8.and_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; default: goto parse_error; } } case 'c': - if (strcmp(op, "i32.atomic.rmw8.cmpxchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw8.cmpxchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'o': - if (strcmp(op, "i32.atomic.rmw8.or_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw8.or_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 's': - if (strcmp(op, "i32.atomic.rmw8.sub_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw8.sub_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'x': { switch (op[17]) { case 'c': - if (strcmp(op, "i32.atomic.rmw8.xchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw8.xchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; case 'o': - if (strcmp(op, "i32.atomic.rmw8.xor_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } + if (op == "i32.atomic.rmw8.xor_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i32); } goto parse_error; default: goto parse_error; } @@ -1359,13 +1362,13 @@ switch (op[0]) { case 's': { switch (op[16]) { case '\0': - if (strcmp(op, "i32.atomic.store") == 0) { return makeStore(s, Type::i32, /*isAtomic=*/true); } + if (op == "i32.atomic.store"sv) { return makeStore(s, Type::i32, /*isAtomic=*/true); } goto parse_error; case '1': - if (strcmp(op, "i32.atomic.store16") == 0) { return makeStore(s, Type::i32, /*isAtomic=*/true); } + if (op == "i32.atomic.store16"sv) { return makeStore(s, Type::i32, /*isAtomic=*/true); } goto parse_error; case '8': - if (strcmp(op, "i32.atomic.store8") == 0) { return makeStore(s, Type::i32, /*isAtomic=*/true); } + if (op == "i32.atomic.store8"sv) { return makeStore(s, Type::i32, /*isAtomic=*/true); } goto parse_error; default: goto parse_error; } @@ -1379,13 +1382,13 @@ switch (op[0]) { case 'c': { switch (op[5]) { case 'l': - if (strcmp(op, "i32.clz") == 0) { return makeUnary(s, UnaryOp::ClzInt32); } + if (op == "i32.clz"sv) { return makeUnary(s, UnaryOp::ClzInt32); } goto parse_error; case 'o': - if (strcmp(op, "i32.const") == 0) { return makeConst(s, Type::i32); } + if (op == "i32.const"sv) { return makeConst(s, Type::i32); } goto parse_error; case 't': - if (strcmp(op, "i32.ctz") == 0) { return makeUnary(s, UnaryOp::CtzInt32); } + if (op == "i32.ctz"sv) { return makeUnary(s, UnaryOp::CtzInt32); } goto parse_error; default: goto parse_error; } @@ -1393,10 +1396,10 @@ switch (op[0]) { case 'd': { switch (op[8]) { case 's': - if (strcmp(op, "i32.div_s") == 0) { return makeBinary(s, BinaryOp::DivSInt32); } + if (op == "i32.div_s"sv) { return makeBinary(s, BinaryOp::DivSInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.div_u") == 0) { return makeBinary(s, BinaryOp::DivUInt32); } + if (op == "i32.div_u"sv) { return makeBinary(s, BinaryOp::DivUInt32); } goto parse_error; default: goto parse_error; } @@ -1406,10 +1409,10 @@ switch (op[0]) { case 'q': { switch (op[6]) { case '\0': - if (strcmp(op, "i32.eq") == 0) { return makeBinary(s, BinaryOp::EqInt32); } + if (op == "i32.eq"sv) { return makeBinary(s, BinaryOp::EqInt32); } goto parse_error; case 'z': - if (strcmp(op, "i32.eqz") == 0) { return makeUnary(s, UnaryOp::EqZInt32); } + if (op == "i32.eqz"sv) { return makeUnary(s, UnaryOp::EqZInt32); } goto parse_error; default: goto parse_error; } @@ -1417,10 +1420,10 @@ switch (op[0]) { case 'x': { switch (op[10]) { case '1': - if (strcmp(op, "i32.extend16_s") == 0) { return makeUnary(s, UnaryOp::ExtendS16Int32); } + if (op == "i32.extend16_s"sv) { return makeUnary(s, UnaryOp::ExtendS16Int32); } goto parse_error; case '8': - if (strcmp(op, "i32.extend8_s") == 0) { return makeUnary(s, UnaryOp::ExtendS8Int32); } + if (op == "i32.extend8_s"sv) { return makeUnary(s, UnaryOp::ExtendS8Int32); } goto parse_error; default: goto parse_error; } @@ -1433,10 +1436,10 @@ switch (op[0]) { case 'e': { switch (op[7]) { case 's': - if (strcmp(op, "i32.ge_s") == 0) { return makeBinary(s, BinaryOp::GeSInt32); } + if (op == "i32.ge_s"sv) { return makeBinary(s, BinaryOp::GeSInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.ge_u") == 0) { return makeBinary(s, BinaryOp::GeUInt32); } + if (op == "i32.ge_u"sv) { return makeBinary(s, BinaryOp::GeUInt32); } goto parse_error; default: goto parse_error; } @@ -1444,10 +1447,10 @@ switch (op[0]) { case 't': { switch (op[7]) { case 's': - if (strcmp(op, "i32.gt_s") == 0) { return makeBinary(s, BinaryOp::GtSInt32); } + if (op == "i32.gt_s"sv) { return makeBinary(s, BinaryOp::GtSInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.gt_u") == 0) { return makeBinary(s, BinaryOp::GtUInt32); } + if (op == "i32.gt_u"sv) { return makeBinary(s, BinaryOp::GtUInt32); } goto parse_error; default: goto parse_error; } @@ -1460,10 +1463,10 @@ switch (op[0]) { case 'e': { switch (op[7]) { case 's': - if (strcmp(op, "i32.le_s") == 0) { return makeBinary(s, BinaryOp::LeSInt32); } + if (op == "i32.le_s"sv) { return makeBinary(s, BinaryOp::LeSInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.le_u") == 0) { return makeBinary(s, BinaryOp::LeUInt32); } + if (op == "i32.le_u"sv) { return makeBinary(s, BinaryOp::LeUInt32); } goto parse_error; default: goto parse_error; } @@ -1471,15 +1474,15 @@ switch (op[0]) { case 'o': { switch (op[8]) { case '\0': - if (strcmp(op, "i32.load") == 0) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } + if (op == "i32.load"sv) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } goto parse_error; case '1': { switch (op[11]) { case 's': - if (strcmp(op, "i32.load16_s") == 0) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } + if (op == "i32.load16_s"sv) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } goto parse_error; case 'u': - if (strcmp(op, "i32.load16_u") == 0) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } + if (op == "i32.load16_u"sv) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } goto parse_error; default: goto parse_error; } @@ -1487,10 +1490,10 @@ switch (op[0]) { case '8': { switch (op[10]) { case 's': - if (strcmp(op, "i32.load8_s") == 0) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } + if (op == "i32.load8_s"sv) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } goto parse_error; case 'u': - if (strcmp(op, "i32.load8_u") == 0) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } + if (op == "i32.load8_u"sv) { return makeLoad(s, Type::i32, /*isAtomic=*/false); } goto parse_error; default: goto parse_error; } @@ -1501,10 +1504,10 @@ switch (op[0]) { case 't': { switch (op[7]) { case 's': - if (strcmp(op, "i32.lt_s") == 0) { return makeBinary(s, BinaryOp::LtSInt32); } + if (op == "i32.lt_s"sv) { return makeBinary(s, BinaryOp::LtSInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.lt_u") == 0) { return makeBinary(s, BinaryOp::LtUInt32); } + if (op == "i32.lt_u"sv) { return makeBinary(s, BinaryOp::LtUInt32); } goto parse_error; default: goto parse_error; } @@ -1513,31 +1516,31 @@ switch (op[0]) { } } case 'm': - if (strcmp(op, "i32.mul") == 0) { return makeBinary(s, BinaryOp::MulInt32); } + if (op == "i32.mul"sv) { return makeBinary(s, BinaryOp::MulInt32); } goto parse_error; case 'n': - if (strcmp(op, "i32.ne") == 0) { return makeBinary(s, BinaryOp::NeInt32); } + if (op == "i32.ne"sv) { return makeBinary(s, BinaryOp::NeInt32); } goto parse_error; case 'o': - if (strcmp(op, "i32.or") == 0) { return makeBinary(s, BinaryOp::OrInt32); } + if (op == "i32.or"sv) { return makeBinary(s, BinaryOp::OrInt32); } goto parse_error; case 'p': - if (strcmp(op, "i32.popcnt") == 0) { return makeUnary(s, UnaryOp::PopcntInt32); } + if (op == "i32.popcnt"sv) { return makeUnary(s, UnaryOp::PopcntInt32); } goto parse_error; case 'r': { switch (op[5]) { case 'e': { switch (op[6]) { case 'i': - if (strcmp(op, "i32.reinterpret_f32") == 0) { return makeUnary(s, UnaryOp::ReinterpretFloat32); } + if (op == "i32.reinterpret_f32"sv) { return makeUnary(s, UnaryOp::ReinterpretFloat32); } goto parse_error; case 'm': { switch (op[8]) { case 's': - if (strcmp(op, "i32.rem_s") == 0) { return makeBinary(s, BinaryOp::RemSInt32); } + if (op == "i32.rem_s"sv) { return makeBinary(s, BinaryOp::RemSInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.rem_u") == 0) { return makeBinary(s, BinaryOp::RemUInt32); } + if (op == "i32.rem_u"sv) { return makeBinary(s, BinaryOp::RemUInt32); } goto parse_error; default: goto parse_error; } @@ -1548,10 +1551,10 @@ switch (op[0]) { case 'o': { switch (op[7]) { case 'l': - if (strcmp(op, "i32.rotl") == 0) { return makeBinary(s, BinaryOp::RotLInt32); } + if (op == "i32.rotl"sv) { return makeBinary(s, BinaryOp::RotLInt32); } goto parse_error; case 'r': - if (strcmp(op, "i32.rotr") == 0) { return makeBinary(s, BinaryOp::RotRInt32); } + if (op == "i32.rotr"sv) { return makeBinary(s, BinaryOp::RotRInt32); } goto parse_error; default: goto parse_error; } @@ -1564,15 +1567,15 @@ switch (op[0]) { case 'h': { switch (op[6]) { case 'l': - if (strcmp(op, "i32.shl") == 0) { return makeBinary(s, BinaryOp::ShlInt32); } + if (op == "i32.shl"sv) { return makeBinary(s, BinaryOp::ShlInt32); } goto parse_error; case 'r': { switch (op[8]) { case 's': - if (strcmp(op, "i32.shr_s") == 0) { return makeBinary(s, BinaryOp::ShrSInt32); } + if (op == "i32.shr_s"sv) { return makeBinary(s, BinaryOp::ShrSInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.shr_u") == 0) { return makeBinary(s, BinaryOp::ShrUInt32); } + if (op == "i32.shr_u"sv) { return makeBinary(s, BinaryOp::ShrUInt32); } goto parse_error; default: goto parse_error; } @@ -1583,19 +1586,19 @@ switch (op[0]) { case 't': { switch (op[9]) { case '\0': - if (strcmp(op, "i32.store") == 0) { return makeStore(s, Type::i32, /*isAtomic=*/false); } + if (op == "i32.store"sv) { return makeStore(s, Type::i32, /*isAtomic=*/false); } goto parse_error; case '1': - if (strcmp(op, "i32.store16") == 0) { return makeStore(s, Type::i32, /*isAtomic=*/false); } + if (op == "i32.store16"sv) { return makeStore(s, Type::i32, /*isAtomic=*/false); } goto parse_error; case '8': - if (strcmp(op, "i32.store8") == 0) { return makeStore(s, Type::i32, /*isAtomic=*/false); } + if (op == "i32.store8"sv) { return makeStore(s, Type::i32, /*isAtomic=*/false); } goto parse_error; default: goto parse_error; } } case 'u': - if (strcmp(op, "i32.sub") == 0) { return makeBinary(s, BinaryOp::SubInt32); } + if (op == "i32.sub"sv) { return makeBinary(s, BinaryOp::SubInt32); } goto parse_error; default: goto parse_error; } @@ -1607,10 +1610,10 @@ switch (op[0]) { case '3': { switch (op[14]) { case 's': - if (strcmp(op, "i32.trunc_f32_s") == 0) { return makeUnary(s, UnaryOp::TruncSFloat32ToInt32); } + if (op == "i32.trunc_f32_s"sv) { return makeUnary(s, UnaryOp::TruncSFloat32ToInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.trunc_f32_u") == 0) { return makeUnary(s, UnaryOp::TruncUFloat32ToInt32); } + if (op == "i32.trunc_f32_u"sv) { return makeUnary(s, UnaryOp::TruncUFloat32ToInt32); } goto parse_error; default: goto parse_error; } @@ -1618,10 +1621,10 @@ switch (op[0]) { case '6': { switch (op[14]) { case 's': - if (strcmp(op, "i32.trunc_f64_s") == 0) { return makeUnary(s, UnaryOp::TruncSFloat64ToInt32); } + if (op == "i32.trunc_f64_s"sv) { return makeUnary(s, UnaryOp::TruncSFloat64ToInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.trunc_f64_u") == 0) { return makeUnary(s, UnaryOp::TruncUFloat64ToInt32); } + if (op == "i32.trunc_f64_u"sv) { return makeUnary(s, UnaryOp::TruncUFloat64ToInt32); } goto parse_error; default: goto parse_error; } @@ -1634,10 +1637,10 @@ switch (op[0]) { case '3': { switch (op[18]) { case 's': - if (strcmp(op, "i32.trunc_sat_f32_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSFloat32ToInt32); } + if (op == "i32.trunc_sat_f32_s"sv) { return makeUnary(s, UnaryOp::TruncSatSFloat32ToInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.trunc_sat_f32_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUFloat32ToInt32); } + if (op == "i32.trunc_sat_f32_u"sv) { return makeUnary(s, UnaryOp::TruncSatUFloat32ToInt32); } goto parse_error; default: goto parse_error; } @@ -1645,10 +1648,10 @@ switch (op[0]) { case '6': { switch (op[18]) { case 's': - if (strcmp(op, "i32.trunc_sat_f64_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSFloat64ToInt32); } + if (op == "i32.trunc_sat_f64_s"sv) { return makeUnary(s, UnaryOp::TruncSatSFloat64ToInt32); } goto parse_error; case 'u': - if (strcmp(op, "i32.trunc_sat_f64_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUFloat64ToInt32); } + if (op == "i32.trunc_sat_f64_u"sv) { return makeUnary(s, UnaryOp::TruncSatUFloat64ToInt32); } goto parse_error; default: goto parse_error; } @@ -1660,10 +1663,10 @@ switch (op[0]) { } } case 'w': - if (strcmp(op, "i32.wrap_i64") == 0) { return makeUnary(s, UnaryOp::WrapInt64); } + if (op == "i32.wrap_i64"sv) { return makeUnary(s, UnaryOp::WrapInt64); } goto parse_error; case 'x': - if (strcmp(op, "i32.xor") == 0) { return makeBinary(s, BinaryOp::XorInt32); } + if (op == "i32.xor"sv) { return makeBinary(s, BinaryOp::XorInt32); } goto parse_error; default: goto parse_error; } @@ -1673,27 +1676,27 @@ switch (op[0]) { case 'a': { switch (op[7]) { case 'b': - if (strcmp(op, "i32x4.abs") == 0) { return makeUnary(s, UnaryOp::AbsVecI32x4); } + if (op == "i32x4.abs"sv) { return makeUnary(s, UnaryOp::AbsVecI32x4); } goto parse_error; case 'd': - if (strcmp(op, "i32x4.add") == 0) { return makeBinary(s, BinaryOp::AddVecI32x4); } + if (op == "i32x4.add"sv) { return makeBinary(s, BinaryOp::AddVecI32x4); } goto parse_error; case 'l': - if (strcmp(op, "i32x4.all_true") == 0) { return makeUnary(s, UnaryOp::AllTrueVecI32x4); } + if (op == "i32x4.all_true"sv) { return makeUnary(s, UnaryOp::AllTrueVecI32x4); } goto parse_error; default: goto parse_error; } } case 'b': - if (strcmp(op, "i32x4.bitmask") == 0) { return makeUnary(s, UnaryOp::BitmaskVecI32x4); } + if (op == "i32x4.bitmask"sv) { return makeUnary(s, UnaryOp::BitmaskVecI32x4); } goto parse_error; case 'd': { switch (op[11]) { case '1': - if (strcmp(op, "i32x4.dot_i16x8_s") == 0) { return makeBinary(s, BinaryOp::DotSVecI16x8ToVecI32x4); } + if (op == "i32x4.dot_i16x8_s"sv) { return makeBinary(s, BinaryOp::DotSVecI16x8ToVecI32x4); } goto parse_error; case '8': - if (strcmp(op, "i32x4.dot_i8x16_i7x16_add_s") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::DotI8x16I7x16AddSToVecI32x4); } + if (op == "i32x4.dot_i8x16_i7x16_add_s"sv) { return makeSIMDTernary(s, SIMDTernaryOp::DotI8x16I7x16AddSToVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1701,17 +1704,17 @@ switch (op[0]) { case 'e': { switch (op[7]) { case 'q': - if (strcmp(op, "i32x4.eq") == 0) { return makeBinary(s, BinaryOp::EqVecI32x4); } + if (op == "i32x4.eq"sv) { return makeBinary(s, BinaryOp::EqVecI32x4); } goto parse_error; case 'x': { switch (op[9]) { case 'a': { switch (op[28]) { case 's': - if (strcmp(op, "i32x4.extadd_pairwise_i16x8_s") == 0) { return makeUnary(s, UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4); } + if (op == "i32x4.extadd_pairwise_i16x8_s"sv) { return makeUnary(s, UnaryOp::ExtAddPairwiseSVecI16x8ToI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.extadd_pairwise_i16x8_u") == 0) { return makeUnary(s, UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4); } + if (op == "i32x4.extadd_pairwise_i16x8_u"sv) { return makeUnary(s, UnaryOp::ExtAddPairwiseUVecI16x8ToI32x4); } goto parse_error; default: goto parse_error; } @@ -1721,10 +1724,10 @@ switch (op[0]) { case 'h': { switch (op[24]) { case 's': - if (strcmp(op, "i32x4.extend_high_i16x8_s") == 0) { return makeUnary(s, UnaryOp::ExtendHighSVecI16x8ToVecI32x4); } + if (op == "i32x4.extend_high_i16x8_s"sv) { return makeUnary(s, UnaryOp::ExtendHighSVecI16x8ToVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.extend_high_i16x8_u") == 0) { return makeUnary(s, UnaryOp::ExtendHighUVecI16x8ToVecI32x4); } + if (op == "i32x4.extend_high_i16x8_u"sv) { return makeUnary(s, UnaryOp::ExtendHighUVecI16x8ToVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1732,10 +1735,10 @@ switch (op[0]) { case 'l': { switch (op[23]) { case 's': - if (strcmp(op, "i32x4.extend_low_i16x8_s") == 0) { return makeUnary(s, UnaryOp::ExtendLowSVecI16x8ToVecI32x4); } + if (op == "i32x4.extend_low_i16x8_s"sv) { return makeUnary(s, UnaryOp::ExtendLowSVecI16x8ToVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.extend_low_i16x8_u") == 0) { return makeUnary(s, UnaryOp::ExtendLowUVecI16x8ToVecI32x4); } + if (op == "i32x4.extend_low_i16x8_u"sv) { return makeUnary(s, UnaryOp::ExtendLowUVecI16x8ToVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1748,10 +1751,10 @@ switch (op[0]) { case 'h': { switch (op[24]) { case 's': - if (strcmp(op, "i32x4.extmul_high_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI32x4); } + if (op == "i32x4.extmul_high_i16x8_s"sv) { return makeBinary(s, BinaryOp::ExtMulHighSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.extmul_high_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI32x4); } + if (op == "i32x4.extmul_high_i16x8_u"sv) { return makeBinary(s, BinaryOp::ExtMulHighUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1759,10 +1762,10 @@ switch (op[0]) { case 'l': { switch (op[23]) { case 's': - if (strcmp(op, "i32x4.extmul_low_i16x8_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI32x4); } + if (op == "i32x4.extmul_low_i16x8_s"sv) { return makeBinary(s, BinaryOp::ExtMulLowSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.extmul_low_i16x8_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI32x4); } + if (op == "i32x4.extmul_low_i16x8_u"sv) { return makeBinary(s, BinaryOp::ExtMulLowUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1771,7 +1774,7 @@ switch (op[0]) { } } case 'r': - if (strcmp(op, "i32x4.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI32x4, 4); } + if (op == "i32x4.extract_lane"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI32x4, 4); } goto parse_error; default: goto parse_error; } @@ -1784,10 +1787,10 @@ switch (op[0]) { case 'e': { switch (op[9]) { case 's': - if (strcmp(op, "i32x4.ge_s") == 0) { return makeBinary(s, BinaryOp::GeSVecI32x4); } + if (op == "i32x4.ge_s"sv) { return makeBinary(s, BinaryOp::GeSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.ge_u") == 0) { return makeBinary(s, BinaryOp::GeUVecI32x4); } + if (op == "i32x4.ge_u"sv) { return makeBinary(s, BinaryOp::GeUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1795,10 +1798,10 @@ switch (op[0]) { case 't': { switch (op[9]) { case 's': - if (strcmp(op, "i32x4.gt_s") == 0) { return makeBinary(s, BinaryOp::GtSVecI32x4); } + if (op == "i32x4.gt_s"sv) { return makeBinary(s, BinaryOp::GtSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.gt_u") == 0) { return makeBinary(s, BinaryOp::GtUVecI32x4); } + if (op == "i32x4.gt_u"sv) { return makeBinary(s, BinaryOp::GtUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1809,15 +1812,15 @@ switch (op[0]) { case 'l': { switch (op[7]) { case 'a': - if (strcmp(op, "i32x4.laneselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI32x4); } + if (op == "i32x4.laneselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI32x4); } goto parse_error; case 'e': { switch (op[9]) { case 's': - if (strcmp(op, "i32x4.le_s") == 0) { return makeBinary(s, BinaryOp::LeSVecI32x4); } + if (op == "i32x4.le_s"sv) { return makeBinary(s, BinaryOp::LeSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.le_u") == 0) { return makeBinary(s, BinaryOp::LeUVecI32x4); } + if (op == "i32x4.le_u"sv) { return makeBinary(s, BinaryOp::LeUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1825,10 +1828,10 @@ switch (op[0]) { case 't': { switch (op[9]) { case 's': - if (strcmp(op, "i32x4.lt_s") == 0) { return makeBinary(s, BinaryOp::LtSVecI32x4); } + if (op == "i32x4.lt_s"sv) { return makeBinary(s, BinaryOp::LtSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.lt_u") == 0) { return makeBinary(s, BinaryOp::LtUVecI32x4); } + if (op == "i32x4.lt_u"sv) { return makeBinary(s, BinaryOp::LtUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1841,10 +1844,10 @@ switch (op[0]) { case 'a': { switch (op[10]) { case 's': - if (strcmp(op, "i32x4.max_s") == 0) { return makeBinary(s, BinaryOp::MaxSVecI32x4); } + if (op == "i32x4.max_s"sv) { return makeBinary(s, BinaryOp::MaxSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.max_u") == 0) { return makeBinary(s, BinaryOp::MaxUVecI32x4); } + if (op == "i32x4.max_u"sv) { return makeBinary(s, BinaryOp::MaxUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1852,16 +1855,16 @@ switch (op[0]) { case 'i': { switch (op[10]) { case 's': - if (strcmp(op, "i32x4.min_s") == 0) { return makeBinary(s, BinaryOp::MinSVecI32x4); } + if (op == "i32x4.min_s"sv) { return makeBinary(s, BinaryOp::MinSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.min_u") == 0) { return makeBinary(s, BinaryOp::MinUVecI32x4); } + if (op == "i32x4.min_u"sv) { return makeBinary(s, BinaryOp::MinUVecI32x4); } goto parse_error; default: goto parse_error; } } case 'u': - if (strcmp(op, "i32x4.mul") == 0) { return makeBinary(s, BinaryOp::MulVecI32x4); } + if (op == "i32x4.mul"sv) { return makeBinary(s, BinaryOp::MulVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1869,10 +1872,10 @@ switch (op[0]) { case 'n': { switch (op[8]) { case '\0': - if (strcmp(op, "i32x4.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI32x4); } + if (op == "i32x4.ne"sv) { return makeBinary(s, BinaryOp::NeVecI32x4); } goto parse_error; case 'g': - if (strcmp(op, "i32x4.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI32x4); } + if (op == "i32x4.neg"sv) { return makeUnary(s, UnaryOp::NegVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1884,10 +1887,10 @@ switch (op[0]) { case '3': { switch (op[26]) { case 's': - if (strcmp(op, "i32x4.relaxed_trunc_f32x4_s") == 0) { return makeUnary(s, UnaryOp::RelaxedTruncSVecF32x4ToVecI32x4); } + if (op == "i32x4.relaxed_trunc_f32x4_s"sv) { return makeUnary(s, UnaryOp::RelaxedTruncSVecF32x4ToVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.relaxed_trunc_f32x4_u") == 0) { return makeUnary(s, UnaryOp::RelaxedTruncUVecF32x4ToVecI32x4); } + if (op == "i32x4.relaxed_trunc_f32x4_u"sv) { return makeUnary(s, UnaryOp::RelaxedTruncUVecF32x4ToVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1895,10 +1898,10 @@ switch (op[0]) { case '6': { switch (op[26]) { case 's': - if (strcmp(op, "i32x4.relaxed_trunc_f64x2_s_zero") == 0) { return makeUnary(s, UnaryOp::RelaxedTruncZeroSVecF64x2ToVecI32x4); } + if (op == "i32x4.relaxed_trunc_f64x2_s_zero"sv) { return makeUnary(s, UnaryOp::RelaxedTruncZeroSVecF64x2ToVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.relaxed_trunc_f64x2_u_zero") == 0) { return makeUnary(s, UnaryOp::RelaxedTruncZeroUVecF64x2ToVecI32x4); } + if (op == "i32x4.relaxed_trunc_f64x2_u_zero"sv) { return makeUnary(s, UnaryOp::RelaxedTruncZeroUVecF64x2ToVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1907,7 +1910,7 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "i32x4.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI32x4, 4); } + if (op == "i32x4.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI32x4, 4); } goto parse_error; default: goto parse_error; } @@ -1917,15 +1920,15 @@ switch (op[0]) { case 'h': { switch (op[8]) { case 'l': - if (strcmp(op, "i32x4.shl") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI32x4); } + if (op == "i32x4.shl"sv) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI32x4); } goto parse_error; case 'r': { switch (op[10]) { case 's': - if (strcmp(op, "i32x4.shr_s") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI32x4); } + if (op == "i32x4.shr_s"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.shr_u") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI32x4); } + if (op == "i32x4.shr_u"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1934,10 +1937,10 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "i32x4.splat") == 0) { return makeUnary(s, UnaryOp::SplatVecI32x4); } + if (op == "i32x4.splat"sv) { return makeUnary(s, UnaryOp::SplatVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.sub") == 0) { return makeBinary(s, BinaryOp::SubVecI32x4); } + if (op == "i32x4.sub"sv) { return makeBinary(s, BinaryOp::SubVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1947,10 +1950,10 @@ switch (op[0]) { case '3': { switch (op[22]) { case 's': - if (strcmp(op, "i32x4.trunc_sat_f32x4_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4); } + if (op == "i32x4.trunc_sat_f32x4_s"sv) { return makeUnary(s, UnaryOp::TruncSatSVecF32x4ToVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.trunc_sat_f32x4_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4); } + if (op == "i32x4.trunc_sat_f32x4_u"sv) { return makeUnary(s, UnaryOp::TruncSatUVecF32x4ToVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1958,10 +1961,10 @@ switch (op[0]) { case '6': { switch (op[22]) { case 's': - if (strcmp(op, "i32x4.trunc_sat_f64x2_s_zero") == 0) { return makeUnary(s, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4); } + if (op == "i32x4.trunc_sat_f64x2_s_zero"sv) { return makeUnary(s, UnaryOp::TruncSatZeroSVecF64x2ToVecI32x4); } goto parse_error; case 'u': - if (strcmp(op, "i32x4.trunc_sat_f64x2_u_zero") == 0) { return makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4); } + if (op == "i32x4.trunc_sat_f64x2_u_zero"sv) { return makeUnary(s, UnaryOp::TruncSatZeroUVecF64x2ToVecI32x4); } goto parse_error; default: goto parse_error; } @@ -1985,26 +1988,26 @@ switch (op[0]) { case 'a': { switch (op[5]) { case 'd': - if (strcmp(op, "i64.add") == 0) { return makeBinary(s, BinaryOp::AddInt64); } + if (op == "i64.add"sv) { return makeBinary(s, BinaryOp::AddInt64); } goto parse_error; case 'n': - if (strcmp(op, "i64.and") == 0) { return makeBinary(s, BinaryOp::AndInt64); } + if (op == "i64.and"sv) { return makeBinary(s, BinaryOp::AndInt64); } goto parse_error; case 't': { switch (op[11]) { case 'l': { switch (op[15]) { case '\0': - if (strcmp(op, "i64.atomic.load") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/true); } + if (op == "i64.atomic.load"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/true); } goto parse_error; case '1': - if (strcmp(op, "i64.atomic.load16_u") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/true); } + if (op == "i64.atomic.load16_u"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/true); } goto parse_error; case '3': - if (strcmp(op, "i64.atomic.load32_u") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/true); } + if (op == "i64.atomic.load32_u"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/true); } goto parse_error; case '8': - if (strcmp(op, "i64.atomic.load8_u") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/true); } + if (op == "i64.atomic.load8_u"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/true); } goto parse_error; default: goto parse_error; } @@ -2016,30 +2019,30 @@ switch (op[0]) { case 'a': { switch (op[16]) { case 'd': - if (strcmp(op, "i64.atomic.rmw.add") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw.add"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'n': - if (strcmp(op, "i64.atomic.rmw.and") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw.and"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; default: goto parse_error; } } case 'c': - if (strcmp(op, "i64.atomic.rmw.cmpxchg") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw.cmpxchg"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'o': - if (strcmp(op, "i64.atomic.rmw.or") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw.or"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 's': - if (strcmp(op, "i64.atomic.rmw.sub") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw.sub"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'x': { switch (op[16]) { case 'c': - if (strcmp(op, "i64.atomic.rmw.xchg") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw.xchg"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'o': - if (strcmp(op, "i64.atomic.rmw.xor") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw.xor"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; default: goto parse_error; } @@ -2052,30 +2055,30 @@ switch (op[0]) { case 'a': { switch (op[18]) { case 'd': - if (strcmp(op, "i64.atomic.rmw16.add_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw16.add_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'n': - if (strcmp(op, "i64.atomic.rmw16.and_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw16.and_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; default: goto parse_error; } } case 'c': - if (strcmp(op, "i64.atomic.rmw16.cmpxchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw16.cmpxchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'o': - if (strcmp(op, "i64.atomic.rmw16.or_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw16.or_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 's': - if (strcmp(op, "i64.atomic.rmw16.sub_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw16.sub_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'x': { switch (op[18]) { case 'c': - if (strcmp(op, "i64.atomic.rmw16.xchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw16.xchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'o': - if (strcmp(op, "i64.atomic.rmw16.xor_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw16.xor_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; default: goto parse_error; } @@ -2088,30 +2091,30 @@ switch (op[0]) { case 'a': { switch (op[18]) { case 'd': - if (strcmp(op, "i64.atomic.rmw32.add_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw32.add_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'n': - if (strcmp(op, "i64.atomic.rmw32.and_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw32.and_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; default: goto parse_error; } } case 'c': - if (strcmp(op, "i64.atomic.rmw32.cmpxchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw32.cmpxchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'o': - if (strcmp(op, "i64.atomic.rmw32.or_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw32.or_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 's': - if (strcmp(op, "i64.atomic.rmw32.sub_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw32.sub_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'x': { switch (op[18]) { case 'c': - if (strcmp(op, "i64.atomic.rmw32.xchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw32.xchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'o': - if (strcmp(op, "i64.atomic.rmw32.xor_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw32.xor_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; default: goto parse_error; } @@ -2124,30 +2127,30 @@ switch (op[0]) { case 'a': { switch (op[17]) { case 'd': - if (strcmp(op, "i64.atomic.rmw8.add_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw8.add_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'n': - if (strcmp(op, "i64.atomic.rmw8.and_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw8.and_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; default: goto parse_error; } } case 'c': - if (strcmp(op, "i64.atomic.rmw8.cmpxchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw8.cmpxchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'o': - if (strcmp(op, "i64.atomic.rmw8.or_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw8.or_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 's': - if (strcmp(op, "i64.atomic.rmw8.sub_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw8.sub_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'x': { switch (op[17]) { case 'c': - if (strcmp(op, "i64.atomic.rmw8.xchg_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw8.xchg_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; case 'o': - if (strcmp(op, "i64.atomic.rmw8.xor_u") == 0) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } + if (op == "i64.atomic.rmw8.xor_u"sv) { return makeAtomicRMWOrCmpxchg(s, Type::i64); } goto parse_error; default: goto parse_error; } @@ -2161,16 +2164,16 @@ switch (op[0]) { case 's': { switch (op[16]) { case '\0': - if (strcmp(op, "i64.atomic.store") == 0) { return makeStore(s, Type::i64, /*isAtomic=*/true); } + if (op == "i64.atomic.store"sv) { return makeStore(s, Type::i64, /*isAtomic=*/true); } goto parse_error; case '1': - if (strcmp(op, "i64.atomic.store16") == 0) { return makeStore(s, Type::i64, /*isAtomic=*/true); } + if (op == "i64.atomic.store16"sv) { return makeStore(s, Type::i64, /*isAtomic=*/true); } goto parse_error; case '3': - if (strcmp(op, "i64.atomic.store32") == 0) { return makeStore(s, Type::i64, /*isAtomic=*/true); } + if (op == "i64.atomic.store32"sv) { return makeStore(s, Type::i64, /*isAtomic=*/true); } goto parse_error; case '8': - if (strcmp(op, "i64.atomic.store8") == 0) { return makeStore(s, Type::i64, /*isAtomic=*/true); } + if (op == "i64.atomic.store8"sv) { return makeStore(s, Type::i64, /*isAtomic=*/true); } goto parse_error; default: goto parse_error; } @@ -2184,13 +2187,13 @@ switch (op[0]) { case 'c': { switch (op[5]) { case 'l': - if (strcmp(op, "i64.clz") == 0) { return makeUnary(s, UnaryOp::ClzInt64); } + if (op == "i64.clz"sv) { return makeUnary(s, UnaryOp::ClzInt64); } goto parse_error; case 'o': - if (strcmp(op, "i64.const") == 0) { return makeConst(s, Type::i64); } + if (op == "i64.const"sv) { return makeConst(s, Type::i64); } goto parse_error; case 't': - if (strcmp(op, "i64.ctz") == 0) { return makeUnary(s, UnaryOp::CtzInt64); } + if (op == "i64.ctz"sv) { return makeUnary(s, UnaryOp::CtzInt64); } goto parse_error; default: goto parse_error; } @@ -2198,10 +2201,10 @@ switch (op[0]) { case 'd': { switch (op[8]) { case 's': - if (strcmp(op, "i64.div_s") == 0) { return makeBinary(s, BinaryOp::DivSInt64); } + if (op == "i64.div_s"sv) { return makeBinary(s, BinaryOp::DivSInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.div_u") == 0) { return makeBinary(s, BinaryOp::DivUInt64); } + if (op == "i64.div_u"sv) { return makeBinary(s, BinaryOp::DivUInt64); } goto parse_error; default: goto parse_error; } @@ -2211,10 +2214,10 @@ switch (op[0]) { case 'q': { switch (op[6]) { case '\0': - if (strcmp(op, "i64.eq") == 0) { return makeBinary(s, BinaryOp::EqInt64); } + if (op == "i64.eq"sv) { return makeBinary(s, BinaryOp::EqInt64); } goto parse_error; case 'z': - if (strcmp(op, "i64.eqz") == 0) { return makeUnary(s, UnaryOp::EqZInt64); } + if (op == "i64.eqz"sv) { return makeUnary(s, UnaryOp::EqZInt64); } goto parse_error; default: goto parse_error; } @@ -2222,21 +2225,21 @@ switch (op[0]) { case 'x': { switch (op[10]) { case '1': - if (strcmp(op, "i64.extend16_s") == 0) { return makeUnary(s, UnaryOp::ExtendS16Int64); } + if (op == "i64.extend16_s"sv) { return makeUnary(s, UnaryOp::ExtendS16Int64); } goto parse_error; case '3': - if (strcmp(op, "i64.extend32_s") == 0) { return makeUnary(s, UnaryOp::ExtendS32Int64); } + if (op == "i64.extend32_s"sv) { return makeUnary(s, UnaryOp::ExtendS32Int64); } goto parse_error; case '8': - if (strcmp(op, "i64.extend8_s") == 0) { return makeUnary(s, UnaryOp::ExtendS8Int64); } + if (op == "i64.extend8_s"sv) { return makeUnary(s, UnaryOp::ExtendS8Int64); } goto parse_error; case '_': { switch (op[15]) { case 's': - if (strcmp(op, "i64.extend_i32_s") == 0) { return makeUnary(s, UnaryOp::ExtendSInt32); } + if (op == "i64.extend_i32_s"sv) { return makeUnary(s, UnaryOp::ExtendSInt32); } goto parse_error; case 'u': - if (strcmp(op, "i64.extend_i32_u") == 0) { return makeUnary(s, UnaryOp::ExtendUInt32); } + if (op == "i64.extend_i32_u"sv) { return makeUnary(s, UnaryOp::ExtendUInt32); } goto parse_error; default: goto parse_error; } @@ -2252,10 +2255,10 @@ switch (op[0]) { case 'e': { switch (op[7]) { case 's': - if (strcmp(op, "i64.ge_s") == 0) { return makeBinary(s, BinaryOp::GeSInt64); } + if (op == "i64.ge_s"sv) { return makeBinary(s, BinaryOp::GeSInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.ge_u") == 0) { return makeBinary(s, BinaryOp::GeUInt64); } + if (op == "i64.ge_u"sv) { return makeBinary(s, BinaryOp::GeUInt64); } goto parse_error; default: goto parse_error; } @@ -2263,10 +2266,10 @@ switch (op[0]) { case 't': { switch (op[7]) { case 's': - if (strcmp(op, "i64.gt_s") == 0) { return makeBinary(s, BinaryOp::GtSInt64); } + if (op == "i64.gt_s"sv) { return makeBinary(s, BinaryOp::GtSInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.gt_u") == 0) { return makeBinary(s, BinaryOp::GtUInt64); } + if (op == "i64.gt_u"sv) { return makeBinary(s, BinaryOp::GtUInt64); } goto parse_error; default: goto parse_error; } @@ -2279,10 +2282,10 @@ switch (op[0]) { case 'e': { switch (op[7]) { case 's': - if (strcmp(op, "i64.le_s") == 0) { return makeBinary(s, BinaryOp::LeSInt64); } + if (op == "i64.le_s"sv) { return makeBinary(s, BinaryOp::LeSInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.le_u") == 0) { return makeBinary(s, BinaryOp::LeUInt64); } + if (op == "i64.le_u"sv) { return makeBinary(s, BinaryOp::LeUInt64); } goto parse_error; default: goto parse_error; } @@ -2290,15 +2293,15 @@ switch (op[0]) { case 'o': { switch (op[8]) { case '\0': - if (strcmp(op, "i64.load") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.load"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } goto parse_error; case '1': { switch (op[11]) { case 's': - if (strcmp(op, "i64.load16_s") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.load16_s"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } goto parse_error; case 'u': - if (strcmp(op, "i64.load16_u") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.load16_u"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } goto parse_error; default: goto parse_error; } @@ -2306,10 +2309,10 @@ switch (op[0]) { case '3': { switch (op[11]) { case 's': - if (strcmp(op, "i64.load32_s") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.load32_s"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } goto parse_error; case 'u': - if (strcmp(op, "i64.load32_u") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.load32_u"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } goto parse_error; default: goto parse_error; } @@ -2317,10 +2320,10 @@ switch (op[0]) { case '8': { switch (op[10]) { case 's': - if (strcmp(op, "i64.load8_s") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.load8_s"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } goto parse_error; case 'u': - if (strcmp(op, "i64.load8_u") == 0) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.load8_u"sv) { return makeLoad(s, Type::i64, /*isAtomic=*/false); } goto parse_error; default: goto parse_error; } @@ -2331,10 +2334,10 @@ switch (op[0]) { case 't': { switch (op[7]) { case 's': - if (strcmp(op, "i64.lt_s") == 0) { return makeBinary(s, BinaryOp::LtSInt64); } + if (op == "i64.lt_s"sv) { return makeBinary(s, BinaryOp::LtSInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.lt_u") == 0) { return makeBinary(s, BinaryOp::LtUInt64); } + if (op == "i64.lt_u"sv) { return makeBinary(s, BinaryOp::LtUInt64); } goto parse_error; default: goto parse_error; } @@ -2343,31 +2346,31 @@ switch (op[0]) { } } case 'm': - if (strcmp(op, "i64.mul") == 0) { return makeBinary(s, BinaryOp::MulInt64); } + if (op == "i64.mul"sv) { return makeBinary(s, BinaryOp::MulInt64); } goto parse_error; case 'n': - if (strcmp(op, "i64.ne") == 0) { return makeBinary(s, BinaryOp::NeInt64); } + if (op == "i64.ne"sv) { return makeBinary(s, BinaryOp::NeInt64); } goto parse_error; case 'o': - if (strcmp(op, "i64.or") == 0) { return makeBinary(s, BinaryOp::OrInt64); } + if (op == "i64.or"sv) { return makeBinary(s, BinaryOp::OrInt64); } goto parse_error; case 'p': - if (strcmp(op, "i64.popcnt") == 0) { return makeUnary(s, UnaryOp::PopcntInt64); } + if (op == "i64.popcnt"sv) { return makeUnary(s, UnaryOp::PopcntInt64); } goto parse_error; case 'r': { switch (op[5]) { case 'e': { switch (op[6]) { case 'i': - if (strcmp(op, "i64.reinterpret_f64") == 0) { return makeUnary(s, UnaryOp::ReinterpretFloat64); } + if (op == "i64.reinterpret_f64"sv) { return makeUnary(s, UnaryOp::ReinterpretFloat64); } goto parse_error; case 'm': { switch (op[8]) { case 's': - if (strcmp(op, "i64.rem_s") == 0) { return makeBinary(s, BinaryOp::RemSInt64); } + if (op == "i64.rem_s"sv) { return makeBinary(s, BinaryOp::RemSInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.rem_u") == 0) { return makeBinary(s, BinaryOp::RemUInt64); } + if (op == "i64.rem_u"sv) { return makeBinary(s, BinaryOp::RemUInt64); } goto parse_error; default: goto parse_error; } @@ -2378,10 +2381,10 @@ switch (op[0]) { case 'o': { switch (op[7]) { case 'l': - if (strcmp(op, "i64.rotl") == 0) { return makeBinary(s, BinaryOp::RotLInt64); } + if (op == "i64.rotl"sv) { return makeBinary(s, BinaryOp::RotLInt64); } goto parse_error; case 'r': - if (strcmp(op, "i64.rotr") == 0) { return makeBinary(s, BinaryOp::RotRInt64); } + if (op == "i64.rotr"sv) { return makeBinary(s, BinaryOp::RotRInt64); } goto parse_error; default: goto parse_error; } @@ -2394,15 +2397,15 @@ switch (op[0]) { case 'h': { switch (op[6]) { case 'l': - if (strcmp(op, "i64.shl") == 0) { return makeBinary(s, BinaryOp::ShlInt64); } + if (op == "i64.shl"sv) { return makeBinary(s, BinaryOp::ShlInt64); } goto parse_error; case 'r': { switch (op[8]) { case 's': - if (strcmp(op, "i64.shr_s") == 0) { return makeBinary(s, BinaryOp::ShrSInt64); } + if (op == "i64.shr_s"sv) { return makeBinary(s, BinaryOp::ShrSInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.shr_u") == 0) { return makeBinary(s, BinaryOp::ShrUInt64); } + if (op == "i64.shr_u"sv) { return makeBinary(s, BinaryOp::ShrUInt64); } goto parse_error; default: goto parse_error; } @@ -2413,22 +2416,22 @@ switch (op[0]) { case 't': { switch (op[9]) { case '\0': - if (strcmp(op, "i64.store") == 0) { return makeStore(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.store"sv) { return makeStore(s, Type::i64, /*isAtomic=*/false); } goto parse_error; case '1': - if (strcmp(op, "i64.store16") == 0) { return makeStore(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.store16"sv) { return makeStore(s, Type::i64, /*isAtomic=*/false); } goto parse_error; case '3': - if (strcmp(op, "i64.store32") == 0) { return makeStore(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.store32"sv) { return makeStore(s, Type::i64, /*isAtomic=*/false); } goto parse_error; case '8': - if (strcmp(op, "i64.store8") == 0) { return makeStore(s, Type::i64, /*isAtomic=*/false); } + if (op == "i64.store8"sv) { return makeStore(s, Type::i64, /*isAtomic=*/false); } goto parse_error; default: goto parse_error; } } case 'u': - if (strcmp(op, "i64.sub") == 0) { return makeBinary(s, BinaryOp::SubInt64); } + if (op == "i64.sub"sv) { return makeBinary(s, BinaryOp::SubInt64); } goto parse_error; default: goto parse_error; } @@ -2440,10 +2443,10 @@ switch (op[0]) { case '3': { switch (op[14]) { case 's': - if (strcmp(op, "i64.trunc_f32_s") == 0) { return makeUnary(s, UnaryOp::TruncSFloat32ToInt64); } + if (op == "i64.trunc_f32_s"sv) { return makeUnary(s, UnaryOp::TruncSFloat32ToInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.trunc_f32_u") == 0) { return makeUnary(s, UnaryOp::TruncUFloat32ToInt64); } + if (op == "i64.trunc_f32_u"sv) { return makeUnary(s, UnaryOp::TruncUFloat32ToInt64); } goto parse_error; default: goto parse_error; } @@ -2451,10 +2454,10 @@ switch (op[0]) { case '6': { switch (op[14]) { case 's': - if (strcmp(op, "i64.trunc_f64_s") == 0) { return makeUnary(s, UnaryOp::TruncSFloat64ToInt64); } + if (op == "i64.trunc_f64_s"sv) { return makeUnary(s, UnaryOp::TruncSFloat64ToInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.trunc_f64_u") == 0) { return makeUnary(s, UnaryOp::TruncUFloat64ToInt64); } + if (op == "i64.trunc_f64_u"sv) { return makeUnary(s, UnaryOp::TruncUFloat64ToInt64); } goto parse_error; default: goto parse_error; } @@ -2467,10 +2470,10 @@ switch (op[0]) { case '3': { switch (op[18]) { case 's': - if (strcmp(op, "i64.trunc_sat_f32_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSFloat32ToInt64); } + if (op == "i64.trunc_sat_f32_s"sv) { return makeUnary(s, UnaryOp::TruncSatSFloat32ToInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.trunc_sat_f32_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUFloat32ToInt64); } + if (op == "i64.trunc_sat_f32_u"sv) { return makeUnary(s, UnaryOp::TruncSatUFloat32ToInt64); } goto parse_error; default: goto parse_error; } @@ -2478,10 +2481,10 @@ switch (op[0]) { case '6': { switch (op[18]) { case 's': - if (strcmp(op, "i64.trunc_sat_f64_s") == 0) { return makeUnary(s, UnaryOp::TruncSatSFloat64ToInt64); } + if (op == "i64.trunc_sat_f64_s"sv) { return makeUnary(s, UnaryOp::TruncSatSFloat64ToInt64); } goto parse_error; case 'u': - if (strcmp(op, "i64.trunc_sat_f64_u") == 0) { return makeUnary(s, UnaryOp::TruncSatUFloat64ToInt64); } + if (op == "i64.trunc_sat_f64_u"sv) { return makeUnary(s, UnaryOp::TruncSatUFloat64ToInt64); } goto parse_error; default: goto parse_error; } @@ -2493,7 +2496,7 @@ switch (op[0]) { } } case 'x': - if (strcmp(op, "i64.xor") == 0) { return makeBinary(s, BinaryOp::XorInt64); } + if (op == "i64.xor"sv) { return makeBinary(s, BinaryOp::XorInt64); } goto parse_error; default: goto parse_error; } @@ -2503,24 +2506,24 @@ switch (op[0]) { case 'a': { switch (op[7]) { case 'b': - if (strcmp(op, "i64x2.abs") == 0) { return makeUnary(s, UnaryOp::AbsVecI64x2); } + if (op == "i64x2.abs"sv) { return makeUnary(s, UnaryOp::AbsVecI64x2); } goto parse_error; case 'd': - if (strcmp(op, "i64x2.add") == 0) { return makeBinary(s, BinaryOp::AddVecI64x2); } + if (op == "i64x2.add"sv) { return makeBinary(s, BinaryOp::AddVecI64x2); } goto parse_error; case 'l': - if (strcmp(op, "i64x2.all_true") == 0) { return makeUnary(s, UnaryOp::AllTrueVecI64x2); } + if (op == "i64x2.all_true"sv) { return makeUnary(s, UnaryOp::AllTrueVecI64x2); } goto parse_error; default: goto parse_error; } } case 'b': - if (strcmp(op, "i64x2.bitmask") == 0) { return makeUnary(s, UnaryOp::BitmaskVecI64x2); } + if (op == "i64x2.bitmask"sv) { return makeUnary(s, UnaryOp::BitmaskVecI64x2); } goto parse_error; case 'e': { switch (op[7]) { case 'q': - if (strcmp(op, "i64x2.eq") == 0) { return makeBinary(s, BinaryOp::EqVecI64x2); } + if (op == "i64x2.eq"sv) { return makeBinary(s, BinaryOp::EqVecI64x2); } goto parse_error; case 'x': { switch (op[9]) { @@ -2529,10 +2532,10 @@ switch (op[0]) { case 'h': { switch (op[24]) { case 's': - if (strcmp(op, "i64x2.extend_high_i32x4_s") == 0) { return makeUnary(s, UnaryOp::ExtendHighSVecI32x4ToVecI64x2); } + if (op == "i64x2.extend_high_i32x4_s"sv) { return makeUnary(s, UnaryOp::ExtendHighSVecI32x4ToVecI64x2); } goto parse_error; case 'u': - if (strcmp(op, "i64x2.extend_high_i32x4_u") == 0) { return makeUnary(s, UnaryOp::ExtendHighUVecI32x4ToVecI64x2); } + if (op == "i64x2.extend_high_i32x4_u"sv) { return makeUnary(s, UnaryOp::ExtendHighUVecI32x4ToVecI64x2); } goto parse_error; default: goto parse_error; } @@ -2540,10 +2543,10 @@ switch (op[0]) { case 'l': { switch (op[23]) { case 's': - if (strcmp(op, "i64x2.extend_low_i32x4_s") == 0) { return makeUnary(s, UnaryOp::ExtendLowSVecI32x4ToVecI64x2); } + if (op == "i64x2.extend_low_i32x4_s"sv) { return makeUnary(s, UnaryOp::ExtendLowSVecI32x4ToVecI64x2); } goto parse_error; case 'u': - if (strcmp(op, "i64x2.extend_low_i32x4_u") == 0) { return makeUnary(s, UnaryOp::ExtendLowUVecI32x4ToVecI64x2); } + if (op == "i64x2.extend_low_i32x4_u"sv) { return makeUnary(s, UnaryOp::ExtendLowUVecI32x4ToVecI64x2); } goto parse_error; default: goto parse_error; } @@ -2556,10 +2559,10 @@ switch (op[0]) { case 'h': { switch (op[24]) { case 's': - if (strcmp(op, "i64x2.extmul_high_i32x4_s") == 0) { return makeBinary(s, BinaryOp::ExtMulHighSVecI64x2); } + if (op == "i64x2.extmul_high_i32x4_s"sv) { return makeBinary(s, BinaryOp::ExtMulHighSVecI64x2); } goto parse_error; case 'u': - if (strcmp(op, "i64x2.extmul_high_i32x4_u") == 0) { return makeBinary(s, BinaryOp::ExtMulHighUVecI64x2); } + if (op == "i64x2.extmul_high_i32x4_u"sv) { return makeBinary(s, BinaryOp::ExtMulHighUVecI64x2); } goto parse_error; default: goto parse_error; } @@ -2567,10 +2570,10 @@ switch (op[0]) { case 'l': { switch (op[23]) { case 's': - if (strcmp(op, "i64x2.extmul_low_i32x4_s") == 0) { return makeBinary(s, BinaryOp::ExtMulLowSVecI64x2); } + if (op == "i64x2.extmul_low_i32x4_s"sv) { return makeBinary(s, BinaryOp::ExtMulLowSVecI64x2); } goto parse_error; case 'u': - if (strcmp(op, "i64x2.extmul_low_i32x4_u") == 0) { return makeBinary(s, BinaryOp::ExtMulLowUVecI64x2); } + if (op == "i64x2.extmul_low_i32x4_u"sv) { return makeBinary(s, BinaryOp::ExtMulLowUVecI64x2); } goto parse_error; default: goto parse_error; } @@ -2579,7 +2582,7 @@ switch (op[0]) { } } case 'r': - if (strcmp(op, "i64x2.extract_lane") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI64x2, 2); } + if (op == "i64x2.extract_lane"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneVecI64x2, 2); } goto parse_error; default: goto parse_error; } @@ -2590,10 +2593,10 @@ switch (op[0]) { case 'g': { switch (op[7]) { case 'e': - if (strcmp(op, "i64x2.ge_s") == 0) { return makeBinary(s, BinaryOp::GeSVecI64x2); } + if (op == "i64x2.ge_s"sv) { return makeBinary(s, BinaryOp::GeSVecI64x2); } goto parse_error; case 't': - if (strcmp(op, "i64x2.gt_s") == 0) { return makeBinary(s, BinaryOp::GtSVecI64x2); } + if (op == "i64x2.gt_s"sv) { return makeBinary(s, BinaryOp::GtSVecI64x2); } goto parse_error; default: goto parse_error; } @@ -2601,48 +2604,48 @@ switch (op[0]) { case 'l': { switch (op[7]) { case 'a': - if (strcmp(op, "i64x2.laneselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI64x2); } + if (op == "i64x2.laneselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI64x2); } goto parse_error; case 'e': - if (strcmp(op, "i64x2.le_s") == 0) { return makeBinary(s, BinaryOp::LeSVecI64x2); } + if (op == "i64x2.le_s"sv) { return makeBinary(s, BinaryOp::LeSVecI64x2); } goto parse_error; case 't': - if (strcmp(op, "i64x2.lt_s") == 0) { return makeBinary(s, BinaryOp::LtSVecI64x2); } + if (op == "i64x2.lt_s"sv) { return makeBinary(s, BinaryOp::LtSVecI64x2); } goto parse_error; default: goto parse_error; } } case 'm': - if (strcmp(op, "i64x2.mul") == 0) { return makeBinary(s, BinaryOp::MulVecI64x2); } + if (op == "i64x2.mul"sv) { return makeBinary(s, BinaryOp::MulVecI64x2); } goto parse_error; case 'n': { switch (op[8]) { case '\0': - if (strcmp(op, "i64x2.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI64x2); } + if (op == "i64x2.ne"sv) { return makeBinary(s, BinaryOp::NeVecI64x2); } goto parse_error; case 'g': - if (strcmp(op, "i64x2.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI64x2); } + if (op == "i64x2.neg"sv) { return makeUnary(s, UnaryOp::NegVecI64x2); } goto parse_error; default: goto parse_error; } } case 'r': - if (strcmp(op, "i64x2.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI64x2, 2); } + if (op == "i64x2.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI64x2, 2); } goto parse_error; case 's': { switch (op[7]) { case 'h': { switch (op[8]) { case 'l': - if (strcmp(op, "i64x2.shl") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI64x2); } + if (op == "i64x2.shl"sv) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI64x2); } goto parse_error; case 'r': { switch (op[10]) { case 's': - if (strcmp(op, "i64x2.shr_s") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI64x2); } + if (op == "i64x2.shr_s"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI64x2); } goto parse_error; case 'u': - if (strcmp(op, "i64x2.shr_u") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI64x2); } + if (op == "i64x2.shr_u"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI64x2); } goto parse_error; default: goto parse_error; } @@ -2651,10 +2654,10 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "i64x2.splat") == 0) { return makeUnary(s, UnaryOp::SplatVecI64x2); } + if (op == "i64x2.splat"sv) { return makeUnary(s, UnaryOp::SplatVecI64x2); } goto parse_error; case 'u': - if (strcmp(op, "i64x2.sub") == 0) { return makeBinary(s, BinaryOp::SubVecI64x2); } + if (op == "i64x2.sub"sv) { return makeBinary(s, BinaryOp::SubVecI64x2); } goto parse_error; default: goto parse_error; } @@ -2670,20 +2673,20 @@ switch (op[0]) { case 'a': { switch (op[7]) { case 'b': - if (strcmp(op, "i8x16.abs") == 0) { return makeUnary(s, UnaryOp::AbsVecI8x16); } + if (op == "i8x16.abs"sv) { return makeUnary(s, UnaryOp::AbsVecI8x16); } goto parse_error; case 'd': { switch (op[9]) { case '\0': - if (strcmp(op, "i8x16.add") == 0) { return makeBinary(s, BinaryOp::AddVecI8x16); } + if (op == "i8x16.add"sv) { return makeBinary(s, BinaryOp::AddVecI8x16); } goto parse_error; case '_': { switch (op[14]) { case 's': - if (strcmp(op, "i8x16.add_sat_s") == 0) { return makeBinary(s, BinaryOp::AddSatSVecI8x16); } + if (op == "i8x16.add_sat_s"sv) { return makeBinary(s, BinaryOp::AddSatSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.add_sat_u") == 0) { return makeBinary(s, BinaryOp::AddSatUVecI8x16); } + if (op == "i8x16.add_sat_u"sv) { return makeBinary(s, BinaryOp::AddSatUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2692,29 +2695,29 @@ switch (op[0]) { } } case 'l': - if (strcmp(op, "i8x16.all_true") == 0) { return makeUnary(s, UnaryOp::AllTrueVecI8x16); } + if (op == "i8x16.all_true"sv) { return makeUnary(s, UnaryOp::AllTrueVecI8x16); } goto parse_error; case 'v': - if (strcmp(op, "i8x16.avgr_u") == 0) { return makeBinary(s, BinaryOp::AvgrUVecI8x16); } + if (op == "i8x16.avgr_u"sv) { return makeBinary(s, BinaryOp::AvgrUVecI8x16); } goto parse_error; default: goto parse_error; } } case 'b': - if (strcmp(op, "i8x16.bitmask") == 0) { return makeUnary(s, UnaryOp::BitmaskVecI8x16); } + if (op == "i8x16.bitmask"sv) { return makeUnary(s, UnaryOp::BitmaskVecI8x16); } goto parse_error; case 'e': { switch (op[7]) { case 'q': - if (strcmp(op, "i8x16.eq") == 0) { return makeBinary(s, BinaryOp::EqVecI8x16); } + if (op == "i8x16.eq"sv) { return makeBinary(s, BinaryOp::EqVecI8x16); } goto parse_error; case 'x': { switch (op[19]) { case 's': - if (strcmp(op, "i8x16.extract_lane_s") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI8x16, 16); } + if (op == "i8x16.extract_lane_s"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneSVecI8x16, 16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.extract_lane_u") == 0) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI8x16, 16); } + if (op == "i8x16.extract_lane_u"sv) { return makeSIMDExtract(s, SIMDExtractOp::ExtractLaneUVecI8x16, 16); } goto parse_error; default: goto parse_error; } @@ -2727,10 +2730,10 @@ switch (op[0]) { case 'e': { switch (op[9]) { case 's': - if (strcmp(op, "i8x16.ge_s") == 0) { return makeBinary(s, BinaryOp::GeSVecI8x16); } + if (op == "i8x16.ge_s"sv) { return makeBinary(s, BinaryOp::GeSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.ge_u") == 0) { return makeBinary(s, BinaryOp::GeUVecI8x16); } + if (op == "i8x16.ge_u"sv) { return makeBinary(s, BinaryOp::GeUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2738,10 +2741,10 @@ switch (op[0]) { case 't': { switch (op[9]) { case 's': - if (strcmp(op, "i8x16.gt_s") == 0) { return makeBinary(s, BinaryOp::GtSVecI8x16); } + if (op == "i8x16.gt_s"sv) { return makeBinary(s, BinaryOp::GtSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.gt_u") == 0) { return makeBinary(s, BinaryOp::GtUVecI8x16); } + if (op == "i8x16.gt_u"sv) { return makeBinary(s, BinaryOp::GtUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2752,15 +2755,15 @@ switch (op[0]) { case 'l': { switch (op[7]) { case 'a': - if (strcmp(op, "i8x16.laneselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI8x16); } + if (op == "i8x16.laneselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::LaneselectI8x16); } goto parse_error; case 'e': { switch (op[9]) { case 's': - if (strcmp(op, "i8x16.le_s") == 0) { return makeBinary(s, BinaryOp::LeSVecI8x16); } + if (op == "i8x16.le_s"sv) { return makeBinary(s, BinaryOp::LeSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.le_u") == 0) { return makeBinary(s, BinaryOp::LeUVecI8x16); } + if (op == "i8x16.le_u"sv) { return makeBinary(s, BinaryOp::LeUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2768,10 +2771,10 @@ switch (op[0]) { case 't': { switch (op[9]) { case 's': - if (strcmp(op, "i8x16.lt_s") == 0) { return makeBinary(s, BinaryOp::LtSVecI8x16); } + if (op == "i8x16.lt_s"sv) { return makeBinary(s, BinaryOp::LtSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.lt_u") == 0) { return makeBinary(s, BinaryOp::LtUVecI8x16); } + if (op == "i8x16.lt_u"sv) { return makeBinary(s, BinaryOp::LtUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2784,10 +2787,10 @@ switch (op[0]) { case 'a': { switch (op[10]) { case 's': - if (strcmp(op, "i8x16.max_s") == 0) { return makeBinary(s, BinaryOp::MaxSVecI8x16); } + if (op == "i8x16.max_s"sv) { return makeBinary(s, BinaryOp::MaxSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.max_u") == 0) { return makeBinary(s, BinaryOp::MaxUVecI8x16); } + if (op == "i8x16.max_u"sv) { return makeBinary(s, BinaryOp::MaxUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2795,10 +2798,10 @@ switch (op[0]) { case 'i': { switch (op[10]) { case 's': - if (strcmp(op, "i8x16.min_s") == 0) { return makeBinary(s, BinaryOp::MinSVecI8x16); } + if (op == "i8x16.min_s"sv) { return makeBinary(s, BinaryOp::MinSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.min_u") == 0) { return makeBinary(s, BinaryOp::MinUVecI8x16); } + if (op == "i8x16.min_u"sv) { return makeBinary(s, BinaryOp::MinUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2811,10 +2814,10 @@ switch (op[0]) { case 'a': { switch (op[19]) { case 's': - if (strcmp(op, "i8x16.narrow_i16x8_s") == 0) { return makeBinary(s, BinaryOp::NarrowSVecI16x8ToVecI8x16); } + if (op == "i8x16.narrow_i16x8_s"sv) { return makeBinary(s, BinaryOp::NarrowSVecI16x8ToVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.narrow_i16x8_u") == 0) { return makeBinary(s, BinaryOp::NarrowUVecI16x8ToVecI8x16); } + if (op == "i8x16.narrow_i16x8_u"sv) { return makeBinary(s, BinaryOp::NarrowUVecI16x8ToVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2822,10 +2825,10 @@ switch (op[0]) { case 'e': { switch (op[8]) { case '\0': - if (strcmp(op, "i8x16.ne") == 0) { return makeBinary(s, BinaryOp::NeVecI8x16); } + if (op == "i8x16.ne"sv) { return makeBinary(s, BinaryOp::NeVecI8x16); } goto parse_error; case 'g': - if (strcmp(op, "i8x16.neg") == 0) { return makeUnary(s, UnaryOp::NegVecI8x16); } + if (op == "i8x16.neg"sv) { return makeUnary(s, UnaryOp::NegVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2834,15 +2837,15 @@ switch (op[0]) { } } case 'p': - if (strcmp(op, "i8x16.popcnt") == 0) { return makeUnary(s, UnaryOp::PopcntVecI8x16); } + if (op == "i8x16.popcnt"sv) { return makeUnary(s, UnaryOp::PopcntVecI8x16); } goto parse_error; case 'r': { switch (op[8]) { case 'l': - if (strcmp(op, "i8x16.relaxed_swizzle") == 0) { return makeBinary(s, BinaryOp::RelaxedSwizzleVecI8x16); } + if (op == "i8x16.relaxed_swizzle"sv) { return makeBinary(s, BinaryOp::RelaxedSwizzleVecI8x16); } goto parse_error; case 'p': - if (strcmp(op, "i8x16.replace_lane") == 0) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI8x16, 16); } + if (op == "i8x16.replace_lane"sv) { return makeSIMDReplace(s, SIMDReplaceOp::ReplaceLaneVecI8x16, 16); } goto parse_error; default: goto parse_error; } @@ -2852,40 +2855,40 @@ switch (op[0]) { case 'h': { switch (op[8]) { case 'l': - if (strcmp(op, "i8x16.shl") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI8x16); } + if (op == "i8x16.shl"sv) { return makeSIMDShift(s, SIMDShiftOp::ShlVecI8x16); } goto parse_error; case 'r': { switch (op[10]) { case 's': - if (strcmp(op, "i8x16.shr_s") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI8x16); } + if (op == "i8x16.shr_s"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.shr_u") == 0) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI8x16); } + if (op == "i8x16.shr_u"sv) { return makeSIMDShift(s, SIMDShiftOp::ShrUVecI8x16); } goto parse_error; default: goto parse_error; } } case 'u': - if (strcmp(op, "i8x16.shuffle") == 0) { return makeSIMDShuffle(s); } + if (op == "i8x16.shuffle"sv) { return makeSIMDShuffle(s); } goto parse_error; default: goto parse_error; } } case 'p': - if (strcmp(op, "i8x16.splat") == 0) { return makeUnary(s, UnaryOp::SplatVecI8x16); } + if (op == "i8x16.splat"sv) { return makeUnary(s, UnaryOp::SplatVecI8x16); } goto parse_error; case 'u': { switch (op[9]) { case '\0': - if (strcmp(op, "i8x16.sub") == 0) { return makeBinary(s, BinaryOp::SubVecI8x16); } + if (op == "i8x16.sub"sv) { return makeBinary(s, BinaryOp::SubVecI8x16); } goto parse_error; case '_': { switch (op[14]) { case 's': - if (strcmp(op, "i8x16.sub_sat_s") == 0) { return makeBinary(s, BinaryOp::SubSatSVecI8x16); } + if (op == "i8x16.sub_sat_s"sv) { return makeBinary(s, BinaryOp::SubSatSVecI8x16); } goto parse_error; case 'u': - if (strcmp(op, "i8x16.sub_sat_u") == 0) { return makeBinary(s, BinaryOp::SubSatUVecI8x16); } + if (op == "i8x16.sub_sat_u"sv) { return makeBinary(s, BinaryOp::SubSatUVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2894,7 +2897,7 @@ switch (op[0]) { } } case 'w': - if (strcmp(op, "i8x16.swizzle") == 0) { return makeBinary(s, BinaryOp::SwizzleVecI8x16); } + if (op == "i8x16.swizzle"sv) { return makeBinary(s, BinaryOp::SwizzleVecI8x16); } goto parse_error; default: goto parse_error; } @@ -2903,7 +2906,7 @@ switch (op[0]) { } } case 'f': - if (strcmp(op, "if") == 0) { return makeIf(s); } + if (op == "if"sv) { return makeIf(s); } goto parse_error; default: goto parse_error; } @@ -2913,19 +2916,19 @@ switch (op[0]) { case 'c': { switch (op[6]) { case 'g': - if (strcmp(op, "local.get") == 0) { return makeLocalGet(s); } + if (op == "local.get"sv) { return makeLocalGet(s); } goto parse_error; case 's': - if (strcmp(op, "local.set") == 0) { return makeLocalSet(s); } + if (op == "local.set"sv) { return makeLocalSet(s); } goto parse_error; case 't': - if (strcmp(op, "local.tee") == 0) { return makeLocalTee(s); } + if (op == "local.tee"sv) { return makeLocalTee(s); } goto parse_error; default: goto parse_error; } } case 'o': - if (strcmp(op, "loop") == 0) { return makeLoop(s); } + if (op == "loop"sv) { return makeLoop(s); } goto parse_error; default: goto parse_error; } @@ -2935,15 +2938,15 @@ switch (op[0]) { case 'a': { switch (op[14]) { case 'n': - if (strcmp(op, "memory.atomic.notify") == 0) { return makeAtomicNotify(s); } + if (op == "memory.atomic.notify"sv) { return makeAtomicNotify(s); } goto parse_error; case 'w': { switch (op[18]) { case '3': - if (strcmp(op, "memory.atomic.wait32") == 0) { return makeAtomicWait(s, Type::i32); } + if (op == "memory.atomic.wait32"sv) { return makeAtomicWait(s, Type::i32); } goto parse_error; case '6': - if (strcmp(op, "memory.atomic.wait64") == 0) { return makeAtomicWait(s, Type::i64); } + if (op == "memory.atomic.wait64"sv) { return makeAtomicWait(s, Type::i64); } goto parse_error; default: goto parse_error; } @@ -2952,28 +2955,28 @@ switch (op[0]) { } } case 'c': - if (strcmp(op, "memory.copy") == 0) { return makeMemoryCopy(s); } + if (op == "memory.copy"sv) { return makeMemoryCopy(s); } goto parse_error; case 'f': - if (strcmp(op, "memory.fill") == 0) { return makeMemoryFill(s); } + if (op == "memory.fill"sv) { return makeMemoryFill(s); } goto parse_error; case 'g': - if (strcmp(op, "memory.grow") == 0) { return makeMemoryGrow(s); } + if (op == "memory.grow"sv) { return makeMemoryGrow(s); } goto parse_error; case 'i': - if (strcmp(op, "memory.init") == 0) { return makeMemoryInit(s); } + if (op == "memory.init"sv) { return makeMemoryInit(s); } goto parse_error; case 's': - if (strcmp(op, "memory.size") == 0) { return makeMemorySize(s); } + if (op == "memory.size"sv) { return makeMemorySize(s); } goto parse_error; default: goto parse_error; } } case 'n': - if (strcmp(op, "nop") == 0) { return makeNop(); } + if (op == "nop"sv) { return makeNop(); } goto parse_error; case 'p': - if (strcmp(op, "pop") == 0) { return makePop(s); } + if (op == "pop"sv) { return makePop(s); } goto parse_error; case 'r': { switch (op[2]) { @@ -2982,16 +2985,16 @@ switch (op[0]) { case 'a': { switch (op[7]) { case 'd': - if (strcmp(op, "ref.as_data") == 0) { return makeRefAs(s, RefAsData); } + if (op == "ref.as_data"sv) { return makeRefAs(s, RefAsData); } goto parse_error; case 'f': - if (strcmp(op, "ref.as_func") == 0) { return makeRefAs(s, RefAsFunc); } + if (op == "ref.as_func"sv) { return makeRefAs(s, RefAsFunc); } goto parse_error; case 'i': - if (strcmp(op, "ref.as_i31") == 0) { return makeRefAs(s, RefAsI31); } + if (op == "ref.as_i31"sv) { return makeRefAs(s, RefAsI31); } goto parse_error; case 'n': - if (strcmp(op, "ref.as_non_null") == 0) { return makeRefAs(s, RefAsNonNull); } + if (op == "ref.as_non_null"sv) { return makeRefAs(s, RefAsNonNull); } goto parse_error; default: goto parse_error; } @@ -2999,42 +3002,42 @@ switch (op[0]) { case 'c': { switch (op[9]) { case 'n': - if (strcmp(op, "ref.cast_nop_static") == 0) { return makeRefCastNopStatic(s); } + if (op == "ref.cast_nop_static"sv) { return makeRefCastNopStatic(s); } goto parse_error; case 's': - if (strcmp(op, "ref.cast_static") == 0) { return makeRefCastStatic(s); } + if (op == "ref.cast_static"sv) { return makeRefCastStatic(s); } goto parse_error; default: goto parse_error; } } case 'e': - if (strcmp(op, "ref.eq") == 0) { return makeRefEq(s); } + if (op == "ref.eq"sv) { return makeRefEq(s); } goto parse_error; case 'f': - if (strcmp(op, "ref.func") == 0) { return makeRefFunc(s); } + if (op == "ref.func"sv) { return makeRefFunc(s); } goto parse_error; case 'i': { switch (op[7]) { case 'd': - if (strcmp(op, "ref.is_data") == 0) { return makeRefIs(s, RefIsData); } + if (op == "ref.is_data"sv) { return makeRefIs(s, RefIsData); } goto parse_error; case 'f': - if (strcmp(op, "ref.is_func") == 0) { return makeRefIs(s, RefIsFunc); } + if (op == "ref.is_func"sv) { return makeRefIs(s, RefIsFunc); } goto parse_error; case 'i': - if (strcmp(op, "ref.is_i31") == 0) { return makeRefIs(s, RefIsI31); } + if (op == "ref.is_i31"sv) { return makeRefIs(s, RefIsI31); } goto parse_error; case 'n': - if (strcmp(op, "ref.is_null") == 0) { return makeRefIs(s, RefIsNull); } + if (op == "ref.is_null"sv) { return makeRefIs(s, RefIsNull); } goto parse_error; default: goto parse_error; } } case 'n': - if (strcmp(op, "ref.null") == 0) { return makeRefNull(s); } + if (op == "ref.null"sv) { return makeRefNull(s); } goto parse_error; case 't': - if (strcmp(op, "ref.test_static") == 0) { return makeRefTestStatic(s); } + if (op == "ref.test_static"sv) { return makeRefTestStatic(s); } goto parse_error; default: goto parse_error; } @@ -3042,25 +3045,25 @@ switch (op[0]) { case 't': { switch (op[3]) { case 'h': - if (strcmp(op, "rethrow") == 0) { return makeRethrow(s); } + if (op == "rethrow"sv) { return makeRethrow(s); } goto parse_error; case 'u': { switch (op[6]) { case '\0': - if (strcmp(op, "return") == 0) { return makeReturn(s); } + if (op == "return"sv) { return makeReturn(s); } goto parse_error; case '_': { switch (op[11]) { case '\0': - if (strcmp(op, "return_call") == 0) { return makeCall(s, /*isReturn=*/true); } + if (op == "return_call"sv) { return makeCall(s, /*isReturn=*/true); } goto parse_error; case '_': { switch (op[12]) { case 'i': - if (strcmp(op, "return_call_indirect") == 0) { return makeCallIndirect(s, /*isReturn=*/true); } + if (op == "return_call_indirect"sv) { return makeCallIndirect(s, /*isReturn=*/true); } goto parse_error; case 'r': - if (strcmp(op, "return_call_ref") == 0) { return makeCallRef(s, /*isReturn=*/true); } + if (op == "return_call_ref"sv) { return makeCallRef(s, /*isReturn=*/true); } goto parse_error; default: goto parse_error; } @@ -3080,7 +3083,7 @@ switch (op[0]) { case 's': { switch (op[1]) { case 'e': - if (strcmp(op, "select") == 0) { return makeSelect(s); } + if (op == "select"sv) { return makeSelect(s); } goto parse_error; case 't': { switch (op[3]) { @@ -3091,15 +3094,15 @@ switch (op[0]) { case 'a': { switch (op[10]) { case 'i': - if (strcmp(op, "string.as_iter") == 0) { return makeStringAs(s, StringAsIter); } + if (op == "string.as_iter"sv) { return makeStringAs(s, StringAsIter); } goto parse_error; case 'w': { switch (op[13]) { case '1': - if (strcmp(op, "string.as_wtf16") == 0) { return makeStringAs(s, StringAsWTF16); } + if (op == "string.as_wtf16"sv) { return makeStringAs(s, StringAsWTF16); } goto parse_error; case '8': - if (strcmp(op, "string.as_wtf8") == 0) { return makeStringAs(s, StringAsWTF8); } + if (op == "string.as_wtf8"sv) { return makeStringAs(s, StringAsWTF8); } goto parse_error; default: goto parse_error; } @@ -3110,10 +3113,10 @@ switch (op[0]) { case 'c': { switch (op[10]) { case 'c': - if (strcmp(op, "string.concat") == 0) { return makeStringConcat(s); } + if (op == "string.concat"sv) { return makeStringConcat(s); } goto parse_error; case 's': - if (strcmp(op, "string.const") == 0) { return makeStringConst(s); } + if (op == "string.const"sv) { return makeStringConst(s); } goto parse_error; default: goto parse_error; } @@ -3125,10 +3128,10 @@ switch (op[0]) { case '1': { switch (op[19]) { case '\0': - if (strcmp(op, "string.encode_wtf16") == 0) { return makeStringEncode(s, StringEncodeWTF16); } + if (op == "string.encode_wtf16"sv) { return makeStringEncode(s, StringEncodeWTF16); } goto parse_error; case '_': - if (strcmp(op, "string.encode_wtf16_array") == 0) { return makeStringEncode(s, StringEncodeWTF16Array); } + if (op == "string.encode_wtf16_array"sv) { return makeStringEncode(s, StringEncodeWTF16Array); } goto parse_error; default: goto parse_error; } @@ -3136,10 +3139,10 @@ switch (op[0]) { case '8': { switch (op[18]) { case '\0': - if (strcmp(op, "string.encode_wtf8") == 0) { return makeStringEncode(s, StringEncodeWTF8); } + if (op == "string.encode_wtf8"sv) { return makeStringEncode(s, StringEncodeWTF8); } goto parse_error; case '_': - if (strcmp(op, "string.encode_wtf8_array") == 0) { return makeStringEncode(s, StringEncodeWTF8Array); } + if (op == "string.encode_wtf8_array"sv) { return makeStringEncode(s, StringEncodeWTF8Array); } goto parse_error; default: goto parse_error; } @@ -3148,21 +3151,21 @@ switch (op[0]) { } } case 'q': - if (strcmp(op, "string.eq") == 0) { return makeStringEq(s); } + if (op == "string.eq"sv) { return makeStringEq(s); } goto parse_error; default: goto parse_error; } } case 'i': - if (strcmp(op, "string.is_usv_sequence") == 0) { return makeStringMeasure(s, StringMeasureIsUSV); } + if (op == "string.is_usv_sequence"sv) { return makeStringMeasure(s, StringMeasureIsUSV); } goto parse_error; case 'm': { switch (op[18]) { case '1': - if (strcmp(op, "string.measure_wtf16") == 0) { return makeStringMeasure(s, StringMeasureWTF16); } + if (op == "string.measure_wtf16"sv) { return makeStringMeasure(s, StringMeasureWTF16); } goto parse_error; case '8': - if (strcmp(op, "string.measure_wtf8") == 0) { return makeStringMeasure(s, StringMeasureWTF8); } + if (op == "string.measure_wtf8"sv) { return makeStringMeasure(s, StringMeasureWTF8); } goto parse_error; default: goto parse_error; } @@ -3172,10 +3175,10 @@ switch (op[0]) { case '1': { switch (op[16]) { case '\0': - if (strcmp(op, "string.new_wtf16") == 0) { return makeStringNew(s, StringNewWTF16); } + if (op == "string.new_wtf16"sv) { return makeStringNew(s, StringNewWTF16); } goto parse_error; case '_': - if (strcmp(op, "string.new_wtf16_array") == 0) { return makeStringNew(s, StringNewWTF16Array); } + if (op == "string.new_wtf16_array"sv) { return makeStringNew(s, StringNewWTF16Array); } goto parse_error; default: goto parse_error; } @@ -3183,10 +3186,10 @@ switch (op[0]) { case '8': { switch (op[15]) { case '\0': - if (strcmp(op, "string.new_wtf8") == 0) { return makeStringNew(s, StringNewWTF8); } + if (op == "string.new_wtf8"sv) { return makeStringNew(s, StringNewWTF8); } goto parse_error; case '_': - if (strcmp(op, "string.new_wtf8_array") == 0) { return makeStringNew(s, StringNewWTF8Array); } + if (op == "string.new_wtf8_array"sv) { return makeStringNew(s, StringNewWTF8Array); } goto parse_error; default: goto parse_error; } @@ -3202,16 +3205,16 @@ switch (op[0]) { case 'i': { switch (op[16]) { case 'a': - if (strcmp(op, "stringview_iter.advance") == 0) { return makeStringIterMove(s, StringIterMoveAdvance); } + if (op == "stringview_iter.advance"sv) { return makeStringIterMove(s, StringIterMoveAdvance); } goto parse_error; case 'n': - if (strcmp(op, "stringview_iter.next") == 0) { return makeStringIterNext(s); } + if (op == "stringview_iter.next"sv) { return makeStringIterNext(s); } goto parse_error; case 'r': - if (strcmp(op, "stringview_iter.rewind") == 0) { return makeStringIterMove(s, StringIterMoveRewind); } + if (op == "stringview_iter.rewind"sv) { return makeStringIterMove(s, StringIterMoveRewind); } goto parse_error; case 's': - if (strcmp(op, "stringview_iter.slice") == 0) { return makeStringSliceIter(s); } + if (op == "stringview_iter.slice"sv) { return makeStringSliceIter(s); } goto parse_error; default: goto parse_error; } @@ -3221,13 +3224,13 @@ switch (op[0]) { case '1': { switch (op[17]) { case 'g': - if (strcmp(op, "stringview_wtf16.get_codeunit") == 0) { return makeStringWTF16Get(s); } + if (op == "stringview_wtf16.get_codeunit"sv) { return makeStringWTF16Get(s); } goto parse_error; case 'l': - if (strcmp(op, "stringview_wtf16.length") == 0) { return makeStringMeasure(s, StringMeasureWTF16View); } + if (op == "stringview_wtf16.length"sv) { return makeStringMeasure(s, StringMeasureWTF16View); } goto parse_error; case 's': - if (strcmp(op, "stringview_wtf16.slice") == 0) { return makeStringSliceWTF(s, StringSliceWTF16); } + if (op == "stringview_wtf16.slice"sv) { return makeStringSliceWTF(s, StringSliceWTF16); } goto parse_error; default: goto parse_error; } @@ -3235,10 +3238,10 @@ switch (op[0]) { case '8': { switch (op[16]) { case 'a': - if (strcmp(op, "stringview_wtf8.advance") == 0) { return makeStringWTF8Advance(s); } + if (op == "stringview_wtf8.advance"sv) { return makeStringWTF8Advance(s); } goto parse_error; case 's': - if (strcmp(op, "stringview_wtf8.slice") == 0) { return makeStringSliceWTF(s, StringSliceWTF8); } + if (op == "stringview_wtf8.slice"sv) { return makeStringSliceWTF(s, StringSliceWTF8); } goto parse_error; default: goto parse_error; } @@ -3257,15 +3260,15 @@ switch (op[0]) { case 'g': { switch (op[10]) { case '\0': - if (strcmp(op, "struct.get") == 0) { return makeStructGet(s); } + if (op == "struct.get"sv) { return makeStructGet(s); } goto parse_error; case '_': { switch (op[11]) { case 's': - if (strcmp(op, "struct.get_s") == 0) { return makeStructGet(s, true); } + if (op == "struct.get_s"sv) { return makeStructGet(s, true); } goto parse_error; case 'u': - if (strcmp(op, "struct.get_u") == 0) { return makeStructGet(s, false); } + if (op == "struct.get_u"sv) { return makeStructGet(s, false); } goto parse_error; default: goto parse_error; } @@ -3276,16 +3279,16 @@ switch (op[0]) { case 'n': { switch (op[10]) { case '\0': - if (strcmp(op, "struct.new") == 0) { return makeStructNewStatic(s, false); } + if (op == "struct.new"sv) { return makeStructNewStatic(s, false); } goto parse_error; case '_': - if (strcmp(op, "struct.new_default") == 0) { return makeStructNewStatic(s, true); } + if (op == "struct.new_default"sv) { return makeStructNewStatic(s, true); } goto parse_error; default: goto parse_error; } } case 's': - if (strcmp(op, "struct.set") == 0) { return makeStructSet(s); } + if (op == "struct.set"sv) { return makeStructSet(s); } goto parse_error; default: goto parse_error; } @@ -3303,10 +3306,10 @@ switch (op[0]) { case 'g': { switch (op[7]) { case 'e': - if (strcmp(op, "table.get") == 0) { return makeTableGet(s); } + if (op == "table.get"sv) { return makeTableGet(s); } goto parse_error; case 'r': - if (strcmp(op, "table.grow") == 0) { return makeTableGrow(s); } + if (op == "table.grow"sv) { return makeTableGrow(s); } goto parse_error; default: goto parse_error; } @@ -3314,10 +3317,10 @@ switch (op[0]) { case 's': { switch (op[7]) { case 'e': - if (strcmp(op, "table.set") == 0) { return makeTableSet(s); } + if (op == "table.set"sv) { return makeTableSet(s); } goto parse_error; case 'i': - if (strcmp(op, "table.size") == 0) { return makeTableSize(s); } + if (op == "table.size"sv) { return makeTableSize(s); } goto parse_error; default: goto parse_error; } @@ -3328,24 +3331,24 @@ switch (op[0]) { case 'h': { switch (op[2]) { case 'e': - if (strcmp(op, "then") == 0) { return makeThenOrElse(s); } + if (op == "then"sv) { return makeThenOrElse(s); } goto parse_error; case 'r': - if (strcmp(op, "throw") == 0) { return makeThrow(s); } + if (op == "throw"sv) { return makeThrow(s); } goto parse_error; default: goto parse_error; } } case 'r': - if (strcmp(op, "try") == 0) { return makeTry(s); } + if (op == "try"sv) { return makeTry(s); } goto parse_error; case 'u': { switch (op[6]) { case 'e': - if (strcmp(op, "tuple.extract") == 0) { return makeTupleExtract(s); } + if (op == "tuple.extract"sv) { return makeTupleExtract(s); } goto parse_error; case 'm': - if (strcmp(op, "tuple.make") == 0) { return makeTupleMake(s); } + if (op == "tuple.make"sv) { return makeTupleMake(s); } goto parse_error; default: goto parse_error; } @@ -3354,7 +3357,7 @@ switch (op[0]) { } } case 'u': - if (strcmp(op, "unreachable") == 0) { return makeUnreachable(); } + if (op == "unreachable"sv) { return makeUnreachable(); } goto parse_error; case 'v': { switch (op[5]) { @@ -3363,40 +3366,40 @@ switch (op[0]) { case 'd': { switch (op[8]) { case '\0': - if (strcmp(op, "v128.and") == 0) { return makeBinary(s, BinaryOp::AndVec128); } + if (op == "v128.and"sv) { return makeBinary(s, BinaryOp::AndVec128); } goto parse_error; case 'n': - if (strcmp(op, "v128.andnot") == 0) { return makeBinary(s, BinaryOp::AndNotVec128); } + if (op == "v128.andnot"sv) { return makeBinary(s, BinaryOp::AndNotVec128); } goto parse_error; default: goto parse_error; } } case 'y': - if (strcmp(op, "v128.any_true") == 0) { return makeUnary(s, UnaryOp::AnyTrueVec128); } + if (op == "v128.any_true"sv) { return makeUnary(s, UnaryOp::AnyTrueVec128); } goto parse_error; default: goto parse_error; } } case 'b': - if (strcmp(op, "v128.bitselect") == 0) { return makeSIMDTernary(s, SIMDTernaryOp::Bitselect); } + if (op == "v128.bitselect"sv) { return makeSIMDTernary(s, SIMDTernaryOp::Bitselect); } goto parse_error; case 'c': - if (strcmp(op, "v128.const") == 0) { return makeConst(s, Type::v128); } + if (op == "v128.const"sv) { return makeConst(s, Type::v128); } goto parse_error; case 'l': { switch (op[9]) { case '\0': - if (strcmp(op, "v128.load") == 0) { return makeLoad(s, Type::v128, /*isAtomic=*/false); } + if (op == "v128.load"sv) { return makeLoad(s, Type::v128, /*isAtomic=*/false); } goto parse_error; case '1': { switch (op[11]) { case '_': { switch (op[12]) { case 'l': - if (strcmp(op, "v128.load16_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load16LaneVec128); } + if (op == "v128.load16_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load16LaneVec128); } goto parse_error; case 's': - if (strcmp(op, "v128.load16_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load16SplatVec128); } + if (op == "v128.load16_splat"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load16SplatVec128); } goto parse_error; default: goto parse_error; } @@ -3404,10 +3407,10 @@ switch (op[0]) { case 'x': { switch (op[14]) { case 's': - if (strcmp(op, "v128.load16x4_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load16x4SVec128); } + if (op == "v128.load16x4_s"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load16x4SVec128); } goto parse_error; case 'u': - if (strcmp(op, "v128.load16x4_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load16x4UVec128); } + if (op == "v128.load16x4_u"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load16x4UVec128); } goto parse_error; default: goto parse_error; } @@ -3420,13 +3423,13 @@ switch (op[0]) { case '_': { switch (op[12]) { case 'l': - if (strcmp(op, "v128.load32_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load32LaneVec128); } + if (op == "v128.load32_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load32LaneVec128); } goto parse_error; case 's': - if (strcmp(op, "v128.load32_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32SplatVec128); } + if (op == "v128.load32_splat"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load32SplatVec128); } goto parse_error; case 'z': - if (strcmp(op, "v128.load32_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32ZeroVec128); } + if (op == "v128.load32_zero"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load32ZeroVec128); } goto parse_error; default: goto parse_error; } @@ -3434,10 +3437,10 @@ switch (op[0]) { case 'x': { switch (op[14]) { case 's': - if (strcmp(op, "v128.load32x2_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32x2SVec128); } + if (op == "v128.load32x2_s"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load32x2SVec128); } goto parse_error; case 'u': - if (strcmp(op, "v128.load32x2_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load32x2UVec128); } + if (op == "v128.load32x2_u"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load32x2UVec128); } goto parse_error; default: goto parse_error; } @@ -3448,13 +3451,13 @@ switch (op[0]) { case '6': { switch (op[12]) { case 'l': - if (strcmp(op, "v128.load64_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load64LaneVec128); } + if (op == "v128.load64_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load64LaneVec128); } goto parse_error; case 's': - if (strcmp(op, "v128.load64_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load64SplatVec128); } + if (op == "v128.load64_splat"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load64SplatVec128); } goto parse_error; case 'z': - if (strcmp(op, "v128.load64_zero") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load64ZeroVec128); } + if (op == "v128.load64_zero"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load64ZeroVec128); } goto parse_error; default: goto parse_error; } @@ -3464,10 +3467,10 @@ switch (op[0]) { case '_': { switch (op[11]) { case 'l': - if (strcmp(op, "v128.load8_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load8LaneVec128); } + if (op == "v128.load8_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Load8LaneVec128); } goto parse_error; case 's': - if (strcmp(op, "v128.load8_splat") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load8SplatVec128); } + if (op == "v128.load8_splat"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load8SplatVec128); } goto parse_error; default: goto parse_error; } @@ -3475,10 +3478,10 @@ switch (op[0]) { case 'x': { switch (op[13]) { case 's': - if (strcmp(op, "v128.load8x8_s") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load8x8SVec128); } + if (op == "v128.load8x8_s"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load8x8SVec128); } goto parse_error; case 'u': - if (strcmp(op, "v128.load8x8_u") == 0) { return makeSIMDLoad(s, SIMDLoadOp::Load8x8UVec128); } + if (op == "v128.load8x8_u"sv) { return makeSIMDLoad(s, SIMDLoadOp::Load8x8UVec128); } goto parse_error; default: goto parse_error; } @@ -3490,33 +3493,33 @@ switch (op[0]) { } } case 'n': - if (strcmp(op, "v128.not") == 0) { return makeUnary(s, UnaryOp::NotVec128); } + if (op == "v128.not"sv) { return makeUnary(s, UnaryOp::NotVec128); } goto parse_error; case 'o': - if (strcmp(op, "v128.or") == 0) { return makeBinary(s, BinaryOp::OrVec128); } + if (op == "v128.or"sv) { return makeBinary(s, BinaryOp::OrVec128); } goto parse_error; case 's': { switch (op[10]) { case '\0': - if (strcmp(op, "v128.store") == 0) { return makeStore(s, Type::v128, /*isAtomic=*/false); } + if (op == "v128.store"sv) { return makeStore(s, Type::v128, /*isAtomic=*/false); } goto parse_error; case '1': - if (strcmp(op, "v128.store16_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store16LaneVec128); } + if (op == "v128.store16_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store16LaneVec128); } goto parse_error; case '3': - if (strcmp(op, "v128.store32_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store32LaneVec128); } + if (op == "v128.store32_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store32LaneVec128); } goto parse_error; case '6': - if (strcmp(op, "v128.store64_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store64LaneVec128); } + if (op == "v128.store64_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store64LaneVec128); } goto parse_error; case '8': - if (strcmp(op, "v128.store8_lane") == 0) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store8LaneVec128); } + if (op == "v128.store8_lane"sv) { return makeSIMDLoadStoreLane(s, SIMDLoadStoreLaneOp::Store8LaneVec128); } goto parse_error; default: goto parse_error; } } case 'x': - if (strcmp(op, "v128.xor") == 0) { return makeBinary(s, BinaryOp::XorVec128); } + if (op == "v128.xor"sv) { return makeBinary(s, BinaryOp::XorVec128); } goto parse_error; default: goto parse_error; } diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp index acd446acc..924040e12 100644 --- a/src/ir/ExpressionAnalyzer.cpp +++ b/src/ir/ExpressionAnalyzer.cpp @@ -364,7 +364,7 @@ struct Hasher { rehash(digest, 2); rehash(digest, internalNames[curr]); } - void visitNonScopeName(Name curr) { rehash(digest, uint64_t(curr.str)); } + void visitNonScopeName(Name curr) { rehash(digest, curr); } void visitType(Type curr) { rehash(digest, curr.getID()); } void visitHeapType(HeapType curr) { rehash(digest, curr.getID()); } void visitAddress(Address curr) { rehash(digest, curr.addr); } diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index 8294e1575..a350f0e33 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -353,7 +353,7 @@ void ModuleSplitter::exportImportFunction(Name funcName) { } while (primary.getExportOrNull(exportName) != nullptr); } else { exportName = Names::getValidExportName( - primary, config.newExportPrefix + funcName.c_str()); + primary, config.newExportPrefix + funcName.toString()); } primary.addExport( Builder::makeExport(exportName, funcName, ExternalKind::Function)); @@ -492,8 +492,7 @@ void ModuleSplitter::setupTablePatching() { placeholder->module = config.placeholderNamespace; placeholder->base = std::to_string(index); placeholder->name = Names::getValidFunctionName( - primary, - std::string("placeholder_") + std::string(placeholder->base.c_str())); + primary, std::string("placeholder_") + placeholder->base.toString()); placeholder->hasExplicitName = false; placeholder->type = secondaryFunc->type; elem = placeholder->name; diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp index e5886a348..94ad5859e 100644 --- a/src/passes/Asyncify.cpp +++ b/src/passes/Asyncify.cpp @@ -444,9 +444,9 @@ public: // internal escaped names for later comparisons for (auto& name : list) { auto escaped = WasmBinaryBuilder::escape(name); - unescaped[escaped.str] = name; + unescaped[escaped.toString()] = name; if (name.find('*') != std::string::npos) { - patterns.insert(escaped.str); + patterns.insert(escaped.toString()); } else { auto* func = module.getFunctionOrNull(escaped); if (!func) { @@ -469,7 +469,7 @@ public: return true; } else { for (auto& pattern : patterns) { - if (String::wildcardMatch(pattern, funcName.str)) { + if (String::wildcardMatch(pattern, funcName.toString())) { patternsMatched.insert(pattern); return true; } @@ -1502,7 +1502,7 @@ private: } // anonymous namespace static std::string getFullImportName(Name module, Name base) { - return std::string(module.str) + '.' + base.str; + return std::string(module.str) + '.' + base.toString(); } struct Asyncify : public Pass { diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp index 80818907f..3255208fe 100644 --- a/src/passes/FuncCastEmulation.cpp +++ b/src/passes/FuncCastEmulation.cpp @@ -177,7 +177,7 @@ struct FuncCastEmulation : public Pass { private: // Creates a thunk for a function, casting args and return value as needed. Name makeThunk(Name name, Module* module, Index numParams) { - Name thunk = std::string("byn$fpcast-emu$") + name.str; + Name thunk = std::string("byn$fpcast-emu$") + name.toString(); if (module->getFunctionOrNull(thunk)) { Fatal() << "FuncCastEmulation::makeThunk seems a thunk name already in " "use. Was the pass already run on this code?"; diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp index 313070e9a..aee65c22a 100644 --- a/src/passes/I64ToI32Lowering.cpp +++ b/src/passes/I64ToI32Lowering.cpp @@ -22,13 +22,13 @@ // #include "abi/js.h" -#include "emscripten-optimizer/istring.h" #include "ir/flat.h" #include "ir/iteration.h" #include "ir/memory-utils.h" #include "ir/module-utils.h" #include "ir/names.h" #include "pass.h" +#include "support/istring.h" #include "support/name.h" #include "wasm-builder.h" #include "wasm.h" @@ -36,7 +36,7 @@ namespace wasm { -static Name makeHighName(Name n) { return std::string(n.c_str()) + "$hi"; } +static Name makeHighName(Name n) { return n.toString() + "$hi"; } struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { struct TempVar { @@ -263,7 +263,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { // If this was to an import, we need to call the legal version. This assumes // that legalize-js-interface has been run before. if (fixedCall && getModule()->getFunction(fixedCall->target)->imported()) { - fixedCall->target = std::string("legalfunc$") + fixedCall->target.str; + fixedCall->target = + std::string("legalfunc$") + fixedCall->target.toString(); return; } } diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index f325f70c6..90cf3f5da 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -324,7 +324,7 @@ static Expression* doInlining(Module* module, Type retType = module->getFunction(call->target)->getResults(); Builder builder(*module); auto* block = builder.makeBlock(); - block->name = Name(std::string("__inlined_func$") + from->name.str); + block->name = Name(std::string("__inlined_func$") + from->name.toString()); // In the unlikely event that the function already has a branch target with // this name, fix that up, as otherwise we can get unexpected capture of our // branches, that is, we could end up with this: @@ -767,7 +767,8 @@ private: return ModuleUtils::copyFunction( func, *module, - Names::getValidFunctionName(*module, prefix + '$' + func->name.str)); + Names::getValidFunctionName(*module, + prefix + '$' + func->name.toString())); } // Get the i-th item in a sequence of initial items in an expression. That is, diff --git a/src/passes/JSPI.cpp b/src/passes/JSPI.cpp index fe24d60f7..48f6207ed 100644 --- a/src/passes/JSPI.cpp +++ b/src/passes/JSPI.cpp @@ -88,7 +88,7 @@ struct JSPI : public Pass { private: Name makeWrapperForExport(Function* func, Module* module, Name suspender) { Name wrapperName = Names::getValidFunctionName( - *module, std::string("export$") + func->name.str); + *module, std::string("export$") + func->name.toString()); Builder builder(*module); @@ -137,7 +137,7 @@ private: Builder builder(*module); auto wrapperIm = make_unique<Function>(); wrapperIm->name = Names::getValidFunctionName( - *module, std::string("import$") + im->name.str); + *module, std::string("import$") + im->name.toString()); wrapperIm->module = im->module; wrapperIm->base = im->base; auto stub = make_unique<Function>(); diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp index bbef5109d..f5dbbcf62 100644 --- a/src/passes/LegalizeJSInterface.cpp +++ b/src/passes/LegalizeJSInterface.cpp @@ -90,7 +90,7 @@ struct LegalizeJSInterface : public Pass { // are only called from JS. if (!func->imported() && !isDynCall(ex->name)) { Builder builder(*module); - Name newName = std::string("orig$") + ex->name.str; + Name newName = std::string("orig$") + ex->name.toString(); newExports.push_back(builder.makeExport( newName, func->name, ExternalKind::Function)); } @@ -239,7 +239,7 @@ private: // JS calls the export, so it must call a legal stub that calls the actual // wasm function Name makeLegalStub(Function* func, Module* module) { - Name legalName(std::string("legalstub$") + func->name.str); + Name legalName(std::string("legalstub$") + func->name.toString()); // a method may be exported multiple times if (module->getFunctionOrNull(legalName)) { @@ -292,11 +292,11 @@ private: Name makeLegalStubForCalledImport(Function* im, Module* module) { Builder builder(*module); auto legalIm = make_unique<Function>(); - legalIm->name = Name(std::string("legalimport$") + im->name.str); + legalIm->name = Name(std::string("legalimport$") + im->name.toString()); legalIm->module = im->module; legalIm->base = im->base; auto stub = make_unique<Function>(); - stub->name = Name(std::string("legalfunc$") + im->name.str); + stub->name = Name(std::string("legalfunc$") + im->name.toString()); stub->type = im->type; auto* call = module->allocator.alloc<Call>(); diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp index 98b9c1df7..ed348ef57 100644 --- a/src/passes/MemoryPacking.cpp +++ b/src/passes/MemoryPacking.cpp @@ -569,8 +569,7 @@ void MemoryPacking::createSplitSegments( name = segment->name; hasExplicitName = segment->hasExplicitName; } else { - name = std::string(segment->name.c_str()) + "." + - std::to_string(segmentCount); + name = segment->name.toString() + "." + std::to_string(segmentCount); } segmentCount++; } diff --git a/src/passes/MergeSimilarFunctions.cpp b/src/passes/MergeSimilarFunctions.cpp index e5e50423a..8e039566a 100644 --- a/src/passes/MergeSimilarFunctions.cpp +++ b/src/passes/MergeSimilarFunctions.cpp @@ -526,8 +526,9 @@ bool EquivalentClass::hasMergeBenefit(Module* module, Function* EquivalentClass::createShared(Module* module, const std::vector<ParamInfo>& params) { - Name fnName = Names::getValidFunctionName( - *module, std::string("byn$mgfn-shared$") + primaryFunction->name.str); + Name fnName = Names::getValidFunctionName(*module, + std::string("byn$mgfn-shared$") + + primaryFunction->name.toString()); Builder builder(*module); std::vector<Type> sigParams; Index extraParamBase = primaryFunction->getNumParams(); diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp index 480273da9..35b4241b2 100644 --- a/src/passes/Metrics.cpp +++ b/src/passes/Metrics.cpp @@ -104,7 +104,7 @@ struct Metrics counts["[vars]"] = func->getNumVars(); counts["[binary-bytes]"] = writer.tableOfContents.functionBodies[binaryIndex++].size; - printCounts(std::string("func: ") + func->name.str); + printCounts(std::string("func: ") + func->name.toString()); }); // print for each export how much code size is due to it, i.e., // how much the module could shrink without it. @@ -134,8 +134,8 @@ struct Metrics counts.clear(); counts["[removable-bytes-without-it]"] = baseline - sizeAfterGlobalCleanup(&test); - printCounts(std::string("export: ") + exp->name.str + " (" + - exp->value.str + ')'); + printCounts(std::string("export: ") + exp->name.toString() + " (" + + exp->value.toString() + ')'); } // check how much size depends on the start method if (!module->start.isNull()) { @@ -145,7 +145,7 @@ struct Metrics counts.clear(); counts["[removable-bytes-without-it]"] = baseline - sizeAfterGlobalCleanup(&test); - printCounts(std::string("start: ") + module->start.str); + printCounts(std::string("start: ") + module->start.toString()); } // can't compare detailed info between passes yet lastCounts.clear(); diff --git a/src/passes/Poppify.cpp b/src/passes/Poppify.cpp index 582753c4b..e47b13568 100644 --- a/src/passes/Poppify.cpp +++ b/src/passes/Poppify.cpp @@ -87,8 +87,8 @@ namespace { // Generate names for the elements of tuple globals Name getGlobalElem(Module* module, Name global, Index i) { - return Names::getValidGlobalName( - *module, std::string(global.c_str()) + '$' + std::to_string(i)); + return Names::getValidGlobalName(*module, + global.toString() + '$' + std::to_string(i)); } struct Poppifier : BinaryenIRWriter<Poppifier> { diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp index c936337f3..86b7b8bc3 100644 --- a/src/passes/PostEmscripten.cpp +++ b/src/passes/PostEmscripten.cpp @@ -184,8 +184,6 @@ static void removeData(Module& wasm, << startAddress << ") and " << end_sym << " (" << endAddress << ")"; } -using IString = cashew::IString; - IString EM_JS_PREFIX("__em_js__"); IString EM_JS_DEPS_PREFIX("__em_lib_deps_"); @@ -193,10 +191,10 @@ struct EmJsWalker : public PostWalker<EmJsWalker> { std::vector<Export> toRemove; void visitExport(Export* curr) { - if (curr->name.startsWith(EM_JS_PREFIX.str)) { + if (curr->name.startsWith(EM_JS_PREFIX)) { toRemove.push_back(*curr); } - if (curr->name.startsWith(EM_JS_DEPS_PREFIX.str)) { + if (curr->name.startsWith(EM_JS_DEPS_PREFIX)) { toRemove.push_back(*curr); } } diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 7ebad3322..ddd8f9cc1 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -50,8 +50,13 @@ bool isFullForced() { } std::ostream& printName(Name name, std::ostream& o) { - // we need to quote names if they have tricky chars - if (!name.str || !strpbrk(name.str, "()")) { + assert(name && "Cannot print an empty name"); + // We need to quote names if they have tricky chars. + // TODO: This is not spec-compliant since the spec does not support quoted + // identifiers and has a limited set of valid idchars. We need a more robust + // escaping scheme here. Reusing `printEscapedString` is not sufficient, + // either. + if (name.str.find_first_of("()") == std::string_view::npos) { o << '$' << name.str; } else { o << "\"$" << name.str << '"'; @@ -383,11 +388,9 @@ void processFieldName(Module* wasm, HeapType type, Index index, T func) { func(Name()); } -std::ostream& -printEscapedString(std::ostream& os, const char* data, size_t len) { +std::ostream& printEscapedString(std::ostream& os, std::string_view str) { os << '"'; - for (size_t i = 0; i < len; i++) { - unsigned char c = data[i]; + for (unsigned char c : str) { switch (c) { case '\t': os << "\\t"; @@ -2303,7 +2306,7 @@ struct PrintExpressionContents } void visitStringConst(StringConst* curr) { printMedium(o, "string.const "); - printEscapedString(o, curr->string.c_str(), curr->string.size()); + printEscapedString(o, curr->string.str); } void visitStringMeasure(StringMeasure* curr) { switch (curr->op) { @@ -2926,7 +2929,8 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> { void visitExport(Export* curr) { o << '('; printMedium(o, "export "); - printText(o, curr->name.str) << " ("; + // TODO: Escape the string properly. + printText(o, curr->name.str.data()) << " ("; switch (curr->kind) { case ExternalKind::Function: o << "func"; @@ -2951,8 +2955,9 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> { } void emitImportHeader(Importable* curr) { printMedium(o, "import "); - printText(o, curr->module.str) << ' '; - printText(o, curr->base.str) << ' '; + // TODO: Escape the strings properly and use std::string_view. + printText(o, curr->module.str.data()) << ' '; + printText(o, curr->base.str.data()) << ' '; } void visitGlobal(Global* curr) { if (curr->imported()) { @@ -3233,7 +3238,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> { visit(curr->offset); o << ' '; } - printEscapedString(o, curr->data.data(), curr->data.size()); + printEscapedString(o, {curr->data.data(), curr->data.size()}); o << ')' << maybeNewLine; } void printDylinkSection(const std::unique_ptr<DylinkSection>& dylinkSection) { diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp index c77bff9af..0cafd9d9d 100644 --- a/src/passes/RemoveUnusedModuleElements.cpp +++ b/src/passes/RemoveUnusedModuleElements.cpp @@ -246,7 +246,7 @@ struct RemoveUnusedModuleElements : public Pass { auto startFunction = module->getFunction(module->start); // Can be skipped if the start function is empty. if (!startFunction->imported() && startFunction->body->is<Nop>()) { - module->start.clear(); + module->start = Name{}; } else { roots.emplace_back(ModuleElementKind::Function, module->start); } diff --git a/src/passes/ReorderFunctions.cpp b/src/passes/ReorderFunctions.cpp index b6c7a4984..6c8c55075 100644 --- a/src/passes/ReorderFunctions.cpp +++ b/src/passes/ReorderFunctions.cpp @@ -86,7 +86,7 @@ struct ReorderFunctions : public Pass { [&counts](const std::unique_ptr<Function>& a, const std::unique_ptr<Function>& b) -> bool { if (counts[a->name] == counts[b->name]) { - return strcmp(a->name.str, b->name.str) > 0; + return a->name > b->name; } return counts[a->name] > counts[b->name]; }); diff --git a/src/passes/SetGlobals.cpp b/src/passes/SetGlobals.cpp index 58a82a50b..3bcbb3d31 100644 --- a/src/passes/SetGlobals.cpp +++ b/src/passes/SetGlobals.cpp @@ -34,7 +34,7 @@ struct SetGlobals : public Pass { "SetGlobals usage: wasm-opt --pass-arg=set-globals@x=y,z=w"); // The input is a set of X=Y pairs separated by commas. - String::Split pairs(input.str, ","); + String::Split pairs(input.toString(), ","); for (auto& pair : pairs) { String::Split nameAndValue(pair, "="); auto name = nameAndValue[0]; diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index 4036b8f47..197a59f41 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -638,7 +638,7 @@ static void dumpWast(Name name, Module* wasm) { // TODO: use _getpid() on windows, elsewhere? fullName += std::to_string(getpid()) + '-'; #endif - fullName += numstr + "-" + name.str; + fullName += numstr + "-" + name.toString(); Colors::setEnabled(false); ModuleWriter writer; writer.writeText(*wasm, fullName + ".wast"); diff --git a/src/support/CMakeLists.txt b/src/support/CMakeLists.txt index 0d9350305..a02c1f447 100644 --- a/src/support/CMakeLists.txt +++ b/src/support/CMakeLists.txt @@ -6,6 +6,7 @@ set(support_SOURCES command-line.cpp debug.cpp file.cpp + istring.cpp path.cpp safe_integer.cpp threads.cpp diff --git a/src/support/istring.cpp b/src/support/istring.cpp new file mode 100644 index 000000000..8a3319b5e --- /dev/null +++ b/src/support/istring.cpp @@ -0,0 +1,88 @@ +/* + * Copyright 2022 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 "istring.h" + +namespace wasm { + +std::string_view IString::interned(std::string_view s, bool reuse) { + // We need a set of string_views that can be modified in-place to minimize + // the number of lookups we do. Since set elements cannot normally be + // modified, wrap the string_views in a container that provides mutability + // even through a const reference. + struct MutStringView { + mutable std::string_view str; + MutStringView(std::string_view str) : str(str) {} + }; + struct MutStringViewHash { + size_t operator()(const MutStringView& mut) const { + return std::hash<std::string_view>{}(mut.str); + } + }; + struct MutStringViewEqual { + bool operator()(const MutStringView& a, const MutStringView& b) const { + return a.str == b.str; + } + }; + using StringSet = + std::unordered_set<MutStringView, MutStringViewHash, MutStringViewEqual>; + + // The authoritative global set of interned string views. + static StringSet globalStrings; + + // The global backing store for interned strings that do not otherwise have + // stable addresses. + static std::vector<std::vector<char>> allocated; + + // Guards access to `globalStrings` and `allocated`. + static std::mutex mutex; + + // A thread-local cache of strings to reduce contention. + thread_local static StringSet localStrings; + + auto [localIt, localInserted] = localStrings.insert(s); + if (!localInserted) { + // We already had a local copy of this string. + return localIt->str; + } + + // No copy yet in the local cache. Check the global cache. + std::unique_lock<std::mutex> lock(mutex); + auto [globalIt, globalInserted] = globalStrings.insert(s); + if (!globalInserted) { + // We already had a global copy of this string. Cache it locally. + localIt->str = globalIt->str; + return localIt->str; + } + + if (!reuse) { + // We have a new string, but it doesn't have a stable address. Create a copy + // of the data at a stable address we can use. Make sure it is null + // terminated so legacy uses that get a C string still work. + allocated.emplace_back(); + auto& data = allocated.back(); + data.reserve(s.size() + 1); + data.insert(data.end(), s.begin(), s.end()); + data.push_back('\0'); + s = std::string_view(allocated.back().data(), s.size()); + } + + // Intern our new string. + localIt->str = globalIt->str = s; + return s; +} + +} // namespace wasm diff --git a/src/support/istring.h b/src/support/istring.h new file mode 100644 index 000000000..14f991c30 --- /dev/null +++ b/src/support/istring.h @@ -0,0 +1,110 @@ +/* + * Copyright 2022 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. + */ + +// Interned String type, 100% interned on creation. Comparisons are always just +// a pointer comparison + +#ifndef wasm_support_istring_h +#define wasm_support_istring_h + +#include <set> +#include <string_view> +#include <unordered_set> + +#include <assert.h> + +#include "threads.h" +#include "utilities.h" + +namespace wasm { + +struct IString { +private: + static std::string_view interned(std::string_view s, bool reuse = true); + +public: + const std::string_view str; + + IString() = default; + + // TODO: This is a wildly unsafe default inherited from the previous + // implementation. Change it? + IString(std::string_view str, bool reuse = true) + : str(interned(str, reuse)) {} + + // But other C strings generally do need to be copied. + IString(const char* str) : str(interned(str, false)) {} + IString(const std::string& str) : str(interned(str, false)) {} + + IString(const IString& other) = default; + + IString& operator=(const IString& other) { + return *(new (this) IString(other)); + } + + bool operator==(const IString& other) const { + // Fast! No need to compare contents due to interning + return str.data() == other.str.data(); + } + bool operator!=(const IString& other) const { return !(*this == other); } + bool operator<(const IString& other) const { return str < other.str; } + bool operator<=(const IString& other) const { return str <= other.str; } + bool operator>(const IString& other) const { return str > other.str; } + bool operator>=(const IString& other) const { return str >= other.str; } + + char operator[](int x) const { return str[x]; } + + operator bool() const { return str.data() != nullptr; } + + // TODO: deprecate? + bool is() const { return bool(*this); } + bool isNull() const { return !bool(*this); } + + std::string toString() const { return {str.data(), str.size()}; } + + bool equals(std::string_view other) const { return str == other; } + + bool startsWith(std::string_view prefix) const { + // TODO: Use C++20 `starts_with`. + return str.substr(0, prefix.size()) == prefix; + } + bool startsWith(IString str) const { return startsWith(str.str); } + + // Disambiguate for string literals. + template<int N> bool startsWith(const char (&str)[N]) { + return startsWith(std::string_view(str)); + } + + size_t size() const { return str.size(); } +}; + +} // namespace wasm + +namespace std { + +template<> struct hash<wasm::IString> { + size_t operator()(const wasm::IString& str) const { + return std::hash<size_t>{}(uintptr_t(str.str.data())); + } +}; + +inline std::ostream& operator<<(std::ostream& os, const wasm::IString& str) { + return os << str.str; +} + +} // namespace std + +#endif // wasm_support_istring_h diff --git a/src/support/json.h b/src/support/json.h index a145e1f6b..269b6c0e9 100644 --- a/src/support/json.h +++ b/src/support/json.h @@ -37,12 +37,12 @@ #include <unordered_set> #include <vector> -#include "emscripten-optimizer/istring.h" +#include "support/istring.h" #include "support/safe_integer.h" namespace json { -using IString = cashew::IString; +using IString = wasm::IString; // Main value type struct Value { @@ -112,13 +112,13 @@ struct Value { Value& setString(const char* s) { free(); type = String; - str.set(s); + str = s; return *this; } Value& setString(const IString& s) { free(); type = String; - str.set(s); + str = s; return *this; } Value& setNumber(double n) { @@ -173,7 +173,7 @@ struct Value { const char* getCString() { assert(isString()); - return str.str; + return str.str.data(); } IString& getIString() { assert(isString()); diff --git a/src/support/name.h b/src/support/name.h index 615740e09..a22461d5d 100644 --- a/src/support/name.h +++ b/src/support/name.h @@ -17,9 +17,7 @@ #ifndef wasm_support_name_h #define wasm_support_name_h -#include <string> - -#include "emscripten-optimizer/istring.h" +#include "support/istring.h" namespace wasm { @@ -33,14 +31,19 @@ namespace wasm { // TODO: as an optimization, IString values < some threshold could be considered // numerical indices directly. -struct Name : public cashew::IString { - Name() : cashew::IString() {} - Name(const char* str) : cashew::IString(str, false) {} - Name(cashew::IString str) : cashew::IString(str) {} - Name(const std::string& str) : cashew::IString(str.c_str(), false) {} +struct Name : public IString { + Name() : IString() {} + Name(std::string_view str) : IString(str, false) {} + Name(const char* str) : IString(str, false) {} + Name(IString str) : IString(str) {} + Name(const std::string& str) : IString(str) {} + + // String literals do not need to be copied. Note: Not safe to construct from + // temporary char arrays! Take their address first. + template<size_t N> Name(const char (&str)[N]) : IString(str) {} friend std::ostream& operator<<(std::ostream& o, Name name) { - if (name.str) { + if (name) { return o << name.str; } else { return o << "(null Name)"; @@ -48,11 +51,12 @@ struct Name : public cashew::IString { } static Name fromInt(size_t i) { - return cashew::IString(std::to_string(i).c_str(), false); + return IString(std::to_string(i).c_str(), false); } - bool hasSubstring(cashew::IString substring) { - return strstr(c_str(), substring.c_str()) != nullptr; + bool hasSubstring(IString substring) { + // TODO: Use C++23 `contains`. + return str.find(substring.str) != std::string_view::npos; } }; @@ -60,7 +64,7 @@ struct Name : public cashew::IString { namespace std { -template<> struct hash<wasm::Name> : hash<cashew::IString> {}; +template<> struct hash<wasm::Name> : hash<wasm::IString> {}; } // namespace std diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 09df9ac31..8023ab4da 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -889,7 +889,7 @@ void TranslateToFuzzReader::dropToLog(Function* func) { } void TranslateToFuzzReader::addInvocations(Function* func) { - Name name = func->name.str + std::string("_invoker"); + Name name = func->name.toString() + std::string("_invoker"); if (wasm.getFunctionOrNull(name) || wasm.getExportOrNull(name)) { return; } diff --git a/src/tools/js-wrapper.h b/src/tools/js-wrapper.h index b93948e74..85bc3d7ba 100644 --- a/src/tools/js-wrapper.h +++ b/src/tools/js-wrapper.h @@ -94,15 +94,15 @@ inline std::string generateJSWrapper(Module& wasm) { ret += "if (instance.exports.hangLimitInitializer) " "instance.exports.hangLimitInitializer();\n"; ret += "try {\n"; - ret += std::string(" console.log('[fuzz-exec] calling ") + exp->name.str + - "');\n"; + ret += std::string(" console.log('[fuzz-exec] calling ") + + exp->name.toString() + "');\n"; if (func->getResults() != Type::none) { ret += std::string(" console.log('[fuzz-exec] note result: ") + - exp->name.str + " => ' + literal("; + exp->name.toString() + " => ' + literal("; } else { ret += " "; } - ret += std::string("instance.exports.") + exp->name.str + "("; + ret += std::string("instance.exports.") + exp->name.toString() + "("; bool first = true; for (auto param : func->getParams()) { // zeros in arguments TODO more? diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h index 366e8d4fc..95ead4739 100644 --- a/src/tools/spec-wrapper.h +++ b/src/tools/spec-wrapper.h @@ -32,7 +32,7 @@ inline std::string generateSpecWrapper(Module& wasm) { continue; // something exported other than a function } ret += std::string("(invoke \"hangLimitInitializer\") (invoke \"") + - exp->name.str + "\" "; + exp->name.toString() + "\" "; for (const auto& param : func->getParams()) { // zeros in arguments TODO more? TODO_SINGLE_COMPOUND(param); diff --git a/src/tools/wasm-as.cpp b/src/tools/wasm-as.cpp index 382692273..cc4f6fda2 100644 --- a/src/tools/wasm-as.cpp +++ b/src/tools/wasm-as.cpp @@ -27,7 +27,6 @@ #include "tool-options.h" #include "tool-utils.h" -using namespace cashew; using namespace wasm; int main(int argc, const char* argv[]) { diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 45cc63c37..40abe2f76 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -67,7 +67,8 @@ public: auto* global = wasm.getGlobal(curr->name); if (global->imported()) { throw FailToEvalException(std::string("read from imported global ") + - global->module.str + "." + global->base.str); + global->module.toString() + "." + + global->base.toString()); } return ModuleRunnerBase<EvallingModuleRunner>::visitGlobalGet(curr); @@ -184,13 +185,14 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { auto* globalExport = inst->wasm.getExportOrNull(global->base); if (!globalExport) { throw FailToEvalException(std::string("importGlobals: ") + - global->module.str + "." + - global->base.str); + global->module.toString() + "." + + global->base.toString()); } globals[global->name] = inst->globals[globalExport->value]; } else { throw FailToEvalException(std::string("importGlobals: ") + - global->module.str + "." + global->base.str); + global->module.toString() + "." + + global->base.toString()); } }); } @@ -255,8 +257,8 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { extra = RECOMMENDATION "consider --ignore-external-input"; } throw FailToEvalException(std::string("call import: ") + - import->module.str + "." + import->base.str + - extra); + import->module.toString() + "." + + import->base.toString() + extra); } // We assume the table is not modified FIXME @@ -318,13 +320,14 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { auto* func = wasm->getFunction(targetFunc); if (func->type != sig) { throw FailToEvalException(std::string("callTable signature mismatch: ") + - targetFunc.str); + targetFunc.toString()); } if (!func->imported()) { return instance.callFunctionInternal(targetFunc, arguments); } else { throw FailToEvalException( - std::string("callTable on imported function: ") + targetFunc.str); + std::string("callTable on imported function: ") + + targetFunc.toString()); } } diff --git a/src/tools/wasm-dis.cpp b/src/tools/wasm-dis.cpp index b4003b2c8..e8ca71528 100644 --- a/src/tools/wasm-dis.cpp +++ b/src/tools/wasm-dis.cpp @@ -24,7 +24,6 @@ #include "tool-options.h" -using namespace cashew; using namespace wasm; int main(int argc, const char* argv[]) { diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp index 99d03cec0..0f63e8112 100644 --- a/src/tools/wasm-emscripten-finalize.cpp +++ b/src/tools/wasm-emscripten-finalize.cpp @@ -34,7 +34,6 @@ #define DEBUG_TYPE "emscripten" -using namespace cashew; using namespace wasm; int main(int argc, const char* argv[]) { diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp index 5699b40f2..8a0170f0f 100644 --- a/src/tools/wasm-metadce.cpp +++ b/src/tools/wasm-metadce.cpp @@ -115,19 +115,19 @@ struct MetaDCEGraph { // does not alter parent state, just adds to things pointed by it, // independently (each thread will add for one function, etc.) ModuleUtils::iterDefinedFunctions(wasm, [&](Function* func) { - auto dceName = getName("func", func->name.str); + auto dceName = getName("func", func->name.toString()); DCENodeToFunction[dceName] = func->name; functionToDCENode[func->name] = dceName; nodes[dceName] = DCENode(dceName); }); ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) { - auto dceName = getName("global", global->name.str); + auto dceName = getName("global", global->name.toString()); DCENodeToGlobal[dceName] = global->name; globalToDCENode[global->name] = dceName; nodes[dceName] = DCENode(dceName); }); ModuleUtils::iterDefinedTags(wasm, [&](Tag* tag) { - auto dceName = getName("tag", tag->name.str); + auto dceName = getName("tag", tag->name.toString()); DCENodeToTag[dceName] = tag->name; tagToDCENode[tag->name] = dceName; nodes[dceName] = DCENode(dceName); @@ -137,27 +137,27 @@ struct MetaDCEGraph { ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) { auto id = getImportId(import->module, import->base); if (importIdToDCENode.find(id) == importIdToDCENode.end()) { - auto dceName = getName("importId", import->name.str); + auto dceName = getName("importId", import->name.toString()); importIdToDCENode[id] = dceName; } }); ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) { auto id = getImportId(import->module, import->base); if (importIdToDCENode.find(id) == importIdToDCENode.end()) { - auto dceName = getName("importId", import->name.str); + auto dceName = getName("importId", import->name.toString()); importIdToDCENode[id] = dceName; } }); ModuleUtils::iterImportedTags(wasm, [&](Tag* import) { auto id = getImportId(import->module, import->base); if (importIdToDCENode.find(id) == importIdToDCENode.end()) { - auto dceName = getName("importId", import->name.str); + auto dceName = getName("importId", import->name.toString()); importIdToDCENode[id] = dceName; } }); for (auto& exp : wasm.exports) { if (exportToDCENode.find(exp->name) == exportToDCENode.end()) { - auto dceName = getName("export", exp->name.str); + auto dceName = getName("export", exp->name.toString()); DCENodeToExport[dceName] = exp->name; exportToDCENode[exp->name] = dceName; nodes[dceName] = DCENode(dceName); @@ -368,7 +368,7 @@ public: std::set<std::string> unused; for (auto& [name, _] : nodes) { if (reached.find(name) == reached.end()) { - unused.insert(name.str); + unused.insert(name.toString()); } } for (auto& name : unused) { diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 557e8a770..eec1e0874 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -488,7 +488,7 @@ struct Reducer std::string getLocation() { if (getFunction()) { - return getFunction()->name.str; + return getFunction()->name.toString(); } return "(non-function context)"; } diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index 4b20e922b..61b35e6db 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -31,7 +31,6 @@ #include "wasm-s-parser.h" #include "wasm-validator.h" -using namespace cashew; using namespace wasm; Name ASSERT_RETURN("assert_return"); @@ -162,7 +161,7 @@ protected: instances[name] = instances[lastModule]; Colors::green(std::cerr); - std::cerr << "REGISTER MODULE INSTANCE AS \"" << name.c_str() + std::cerr << "REGISTER MODULE INSTANCE AS \"" << name.str << "\" [line: " << s.line << "]\n"; Colors::normal(std::cerr); } @@ -190,7 +189,7 @@ protected: return instance->getExport(base); } - Fatal() << "Invalid operation " << s[0]->c_str(); + Fatal() << "Invalid operation " << s[0]->toString(); } void parseAssertTrap(Element& s) { diff --git a/src/tools/wasm-split/instrumenter.cpp b/src/tools/wasm-split/instrumenter.cpp index 86a52688e..22940a5f2 100644 --- a/src/tools/wasm-split/instrumenter.cpp +++ b/src/tools/wasm-split/instrumenter.cpp @@ -47,8 +47,8 @@ void Instrumenter::addGlobals(size_t numFuncs) { counterGlobal = Names::getValidGlobalName(*wasm, "monotonic_counter"); functionGlobals.reserve(numFuncs); ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) { - functionGlobals.push_back(Names::getValidGlobalName( - *wasm, std::string(func->name.c_str()) + "_timestamp")); + functionGlobals.push_back( + Names::getValidGlobalName(*wasm, func->name.toString() + "_timestamp")); }); // Create and add new globals diff --git a/src/tools/wasm-split/wasm-split.cpp b/src/tools/wasm-split/wasm-split.cpp index 49a15e934..aa21ec2cb 100644 --- a/src/tools/wasm-split/wasm-split.cpp +++ b/src/tools/wasm-split/wasm-split.cpp @@ -452,7 +452,8 @@ void printReadableProfile(const WasmSplitOptions& options) { auto printFnSet = [&](auto funcs, std::string prefix) { for (auto it = funcs.begin(); it != funcs.end(); ++it) { std::cout << prefix << " " - << (options.unescape ? unescape(it->c_str()) : it->c_str()) + << (options.unescape ? unescape(it->toString()) + : it->toString()) << std::endl; } }; diff --git a/src/tools/wasm2c-wrapper.h b/src/tools/wasm2c-wrapper.h index ae32ec744..f44fc5ca0 100644 --- a/src/tools/wasm2c-wrapper.h +++ b/src/tools/wasm2c-wrapper.h @@ -30,9 +30,7 @@ namespace wasm { inline std::string wasm2cMangle(Name name, Signature sig) { const char escapePrefix = 'Z'; std::string mangled = "Z_"; - const char* original = name.str; - unsigned char c; - while ((c = *original++)) { + for (unsigned char c : name.str) { if ((isalnum(c) && c != escapePrefix) || c == '_') { // This character is ok to emit as it is. mangled += c; @@ -168,14 +166,14 @@ int main(int argc, char** argv) { auto* func = wasm.getFunction(exp->value); ret += std::string(" puts(\"[fuzz-exec] calling ") + - exp->name.str + "\");\n"; + exp->name.toString() + "\");\n"; auto result = func->getResults(); // Emit the call itself. ret += " "; if (result != Type::none) { - ret += std::string("printf(\"[fuzz-exec] note result: ") + exp->name.str + - " => "; + ret += std::string("printf(\"[fuzz-exec] note result: ") + + exp->name.toString() + " => "; TODO_SINGLE_COMPOUND(result); switch (result.getBasic()) { case Type::i32: diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp index 7cecb5f6d..a6430fe12 100644 --- a/src/tools/wasm2js.cpp +++ b/src/tools/wasm2js.cpp @@ -834,7 +834,7 @@ void AssertionEmitter::emit() { )"; Builder wasmBuilder(sexpBuilder.getModule()); - Name asmModule = std::string("ret") + ASM_FUNC.str; + Name asmModule = std::string("ret") + ASM_FUNC.toString(); // Track the last built module. Module wasm; for (size_t i = 0; i < root.size(); ++i) { @@ -843,11 +843,11 @@ void AssertionEmitter::emit() { e[0]->str() == Name("module")) { ModuleUtils::clearModule(wasm); std::stringstream funcNameS; - funcNameS << ASM_FUNC.c_str() << i; + funcNameS << ASM_FUNC << i; std::stringstream moduleNameS; - moduleNameS << "ret" << ASM_FUNC.c_str() << i; - Name funcName(funcNameS.str().c_str()); - asmModule = Name(moduleNameS.str().c_str()); + moduleNameS << "ret" << ASM_FUNC << i; + Name funcName(funcNameS.str()); + asmModule = Name(moduleNameS.str()); options.applyFeatures(wasm); SExpressionWasmBuilder builder(wasm, e, options.profile); emitWasm(wasm, out, flags, options.passOptions, funcName); @@ -857,13 +857,13 @@ void AssertionEmitter::emit() { std::cerr << "skipping " << e << std::endl; continue; } - Name testFuncName(IString(("check" + std::to_string(i)).c_str(), false)); + Name testFuncName("check" + std::to_string(i)); bool isInvoke = (e[0]->str() == Name("invoke")); bool isReturn = (e[0]->str() == Name("assert_return")); bool isReturnNan = (e[0]->str() == Name("assert_return_nan")); if (isInvoke) { emitInvokeFunc(wasmBuilder, wasm, e, testFuncName, asmModule); - out << testFuncName.str << "();\n"; + out << testFuncName << "();\n"; continue; } // Otherwise, this is some form of assertion. @@ -875,7 +875,7 @@ void AssertionEmitter::emit() { emitAssertTrapFunc(wasmBuilder, wasm, e, testFuncName, asmModule); } - out << "if (!" << testFuncName.str << "()) throw 'assertion failed: " << e + out << "if (!" << testFuncName << "()) throw 'assertion failed: " << e << "';\n"; } } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index ca21662e6..bbcfeda53 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1341,8 +1341,8 @@ public: void writeExtraDebugLocation(Expression* curr, Function* func, size_t id); // helpers - void writeInlineString(const char* name); - void writeEscapedName(const char* name); + void writeInlineString(std::string_view name); + void writeEscapedName(std::string_view name); void writeInlineBuffer(const char* data, size_t size); void writeData(const char* data, size_t size); diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 10b84a82f..8f7418719 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -44,8 +44,6 @@ struct WasmException { }; std::ostream& operator<<(std::ostream& o, const WasmException& exn); -using namespace cashew; - // Utilities extern Name WASM, RETURN_FLOW, NONCONSTANT_FLOW; @@ -82,7 +80,7 @@ public: void clearIf(Name target) { if (breakTo == target) { - breakTo.clear(); + breakTo = Name{}; } } @@ -2513,7 +2511,7 @@ public: std::string printFunctionStack() { std::string ret = "/== (binaryen interpreter stack trace)\n"; for (int i = int(functionStack.size()) - 1; i >= 0; i--) { - ret += std::string("|: ") + functionStack[i].str + "\n"; + ret += std::string("|: ") + functionStack[i].toString() + "\n"; } ret += std::string("\\==\n"); return ret; @@ -3505,7 +3503,7 @@ public: // the delegation, don't handle it and just rethrow. if (scope->currDelegateTarget.is()) { if (scope->currDelegateTarget == curr->name) { - scope->currDelegateTarget.clear(); + scope->currDelegateTarget = Name{}; } else { throw; } diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index a7baaa54b..74f0e05e2 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -29,8 +29,6 @@ namespace wasm { -using IString = cashew::IString; - class SourceLocation { public: IString filename; @@ -75,7 +73,7 @@ public: // string methods IString str() const; - const char* c_str() const; + std::string toString() const; Element* setString(IString str__, bool dollared__, bool quoted__); Element* setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_); @@ -168,6 +166,8 @@ private: UniqueNameMapper nameMapper; + int parseIndex(Element& s); + Name getFunctionName(Element& s); Name getTableName(Element& s); Name getMemoryName(Element& s); @@ -186,13 +186,15 @@ private: Type stringToType(IString str, bool allowError = false, bool prefix = false) { return stringToType(str.str, allowError, prefix); } - Type - stringToType(const char* str, bool allowError = false, bool prefix = false); + 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(const char* str, bool prefix = false); + 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); @@ -330,7 +332,8 @@ private: std::vector<NameType>& namedParams); size_t parseTypeUse(Element& s, size_t startPos, HeapType& functionType); - void stringToBinary(const char* input, size_t size, std::vector<char>& data); + void + stringToBinary(Element& s, std::string_view str, std::vector<char>& data); void parseMemory(Element& s, bool preParseImport = false); void parseData(Element& s); void parseInnerData(Element& s, Index i, std::unique_ptr<DataSegment>& seg); diff --git a/src/wasm-type.h b/src/wasm-type.h index dbdbe3d31..36c2cbede 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -21,6 +21,7 @@ #include <optional> #include <ostream> #include <string> +#include <unordered_map> #include <variant> #include <vector> diff --git a/src/wasm.h b/src/wasm.h index 65f70cef9..d20fe8bd5 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -30,6 +30,7 @@ #include <map> #include <ostream> #include <string> +#include <unordered_map> #include <vector> #include "literal.h" diff --git a/src/wasm/parsing.cpp b/src/wasm/parsing.cpp index dc0d332d9..46ec39865 100644 --- a/src/wasm/parsing.cpp +++ b/src/wasm/parsing.cpp @@ -55,7 +55,7 @@ Name UniqueNameMapper::getPrefixedName(Name prefix) { } // make sure to return a unique name not already on the stack while (1) { - Name ret = Name(prefix.str + std::to_string(otherIndex++)); + Name ret = prefix.toString() + std::to_string(otherIndex++); if (reverseLabelMapping.find(ret) == reverseLabelMapping.end()) { return ret; } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index f2698bd79..b9b8558bb 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1263,7 +1263,7 @@ void WasmBinaryWriter::writeLegacyDylinkSection() { o << U32LEB(wasm->dylinkSection->tableAlignment); o << U32LEB(wasm->dylinkSection->neededDynlibs.size()); for (auto& neededDynlib : wasm->dylinkSection->neededDynlibs) { - writeInlineString(neededDynlib.c_str()); + writeInlineString(neededDynlib.str); } finishSection(start); } @@ -1294,7 +1294,7 @@ void WasmBinaryWriter::writeDylinkSection() { startSubsection(BinaryConsts::UserSections::Subsection::DylinkNeeded); o << U32LEB(wasm->dylinkSection->neededDynlibs.size()); for (auto& neededDynlib : wasm->dylinkSection->neededDynlibs) { - writeInlineString(neededDynlib.c_str()); + writeInlineString(neededDynlib.str); } finishSubsection(substart); } @@ -1350,10 +1350,9 @@ void WasmBinaryWriter::writeData(const char* data, size_t size) { } } -void WasmBinaryWriter::writeInlineString(const char* name) { - int32_t size = strlen(name); - o << U32LEB(size); - writeData(name, size); +void WasmBinaryWriter::writeInlineString(std::string_view name) { + o << U32LEB(name.size()); + writeData(name.data(), name.size()); } static bool isHexDigit(char ch) { @@ -1365,19 +1364,17 @@ static int decodeHexNibble(char ch) { return ch <= '9' ? ch & 15 : (ch & 15) + 9; } -void WasmBinaryWriter::writeEscapedName(const char* name) { - assert(name); - if (!strpbrk(name, "\\")) { +void WasmBinaryWriter::writeEscapedName(std::string_view name) { + if (name.find('\\') == std::string_view::npos) { writeInlineString(name); return; } // decode escaped by escapeName (see below) function names std::string unescaped; - int32_t size = strlen(name); - for (int32_t i = 0; i < size;) { + for (size_t i = 0; i < name.size();) { char ch = name[i++]; // support only `\xx` escapes; ignore invalid or unsupported escapes - if (ch != '\\' || i + 1 >= size || !isHexDigit(name[i]) || + if (ch != '\\' || i + 1 >= name.size() || !isHexDigit(name[i]) || !isHexDigit(name[i + 1])) { unescaped.push_back(ch); continue; @@ -1386,7 +1383,7 @@ void WasmBinaryWriter::writeEscapedName(const char* name) { char((decodeHexNibble(name[i]) << 4) | decodeHexNibble(name[i + 1]))); i += 2; } - writeInlineString(unescaped.c_str()); + writeInlineString({unescaped.data(), unescaped.size()}); } void WasmBinaryWriter::writeInlineBuffer(const char* data, size_t size) { @@ -2357,8 +2354,8 @@ void WasmBinaryBuilder::readImports() { functionTypes.push_back(getTypeByIndex(index)); auto type = getTypeByIndex(index); if (!type.isSignature()) { - throwError(std::string("Imported function ") + module.str + '.' + - base.str + + throwError(std::string("Imported function ") + module.toString() + + '.' + base.toString() + "'s type must be a signature. Given: " + type.toString()); } auto curr = builder.makeFunction(name, type, {}); @@ -3268,24 +3265,25 @@ static char formatNibble(int nibble) { Name WasmBinaryBuilder::escape(Name name) { bool allIdChars = true; - for (const char* p = name.str; allIdChars && *p; p++) { - allIdChars = isIdChar(*p); + for (char c : name.str) { + if (!(allIdChars = isIdChar(c))) { + break; + } } if (allIdChars) { return name; } // encode name, if at least one non-idchar (per WebAssembly spec) was found std::string escaped; - for (const char* p = name.str; *p; p++) { - char ch = *p; - if (isIdChar(ch)) { - escaped.push_back(ch); + for (char c : name.str) { + if (isIdChar(c)) { + escaped.push_back(c); continue; } // replace non-idchar with `\xx` escape escaped.push_back('\\'); - escaped.push_back(formatNibble(ch >> 4)); - escaped.push_back(formatNibble(ch & 15)); + escaped.push_back(formatNibble(c >> 4)); + escaped.push_back(formatNibble(c & 15)); } return escaped; } @@ -6839,7 +6837,7 @@ void WasmBinaryBuilder::visitRethrow(Rethrow* curr) { // This special target is valid only for delegates if (curr->target == DELEGATE_CALLER_TARGET) { throwError(std::string("rethrow target cannot use internal name ") + - DELEGATE_CALLER_TARGET.str); + DELEGATE_CALLER_TARGET.toString()); } curr->finalize(); } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 172ef15b6..64d7a21a2 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -54,7 +54,9 @@ static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), ARRAY_SUBTYPE("array_subtype"), EXTENDS("extends"), REC("rec"), I8("i8"), I16("i16"), DECLARE("declare"), ITEM("item"), OFFSET("offset"); -static Address getAddress(const Element* s) { return atoll(s->c_str()); } +static Address getAddress(const Element* s) { + return std::stoll(s->toString()); +} static void checkAddress(Address a, const char* errorText, const Element* errorElem) { @@ -95,11 +97,11 @@ IString Element::str() const { return str_; } -const char* Element::c_str() const { +std::string Element::toString() const { if (!isStr()) { throw ParseException("expected string", line, col); } - return str_.str; + return str_.toString(); } Element* Element::setString(IString str__, bool dollared__, bool quoted__) { @@ -356,11 +358,8 @@ SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm, if (i < module.size() && module[i]->isStr()) { // these s-expressions contain a binary module, actually std::vector<char> data; - while (i < module.size()) { - auto str = module[i++]->c_str(); - if (auto size = strlen(str)) { - stringToBinary(str, size, data); - } + for (; i < module.size(); ++i) { + stringToBinary(*module[i], module[i]->str().str, data); } // TODO: support applying features here WasmBinaryBuilder binaryBuilder(wasm, FeatureSet::MVP, data); @@ -474,12 +473,20 @@ void SExpressionWasmBuilder::parseModuleElement(Element& curr) { throw ParseException("unknown module element", curr.line, curr.col); } +int SExpressionWasmBuilder::parseIndex(Element& s) { + try { + return std::stoi(s.toString()); + } catch (...) { + throw ParseException("expected integer", s.line, s.col); + } +} + Name SExpressionWasmBuilder::getFunctionName(Element& s) { if (s.dollared()) { return s.str(); } else { // index - size_t offset = atoi(s.str().c_str()); + size_t offset = parseIndex(s); if (offset >= functionNames.size()) { throw ParseException( "unknown function in getFunctionName", s.line, s.col); @@ -493,7 +500,7 @@ Name SExpressionWasmBuilder::getTableName(Element& s) { return s.str(); } else { // index - size_t offset = atoi(s.str().c_str()); + size_t offset = parseIndex(s); if (offset >= tableNames.size()) { throw ParseException("unknown table in getTableName", s.line, s.col); } @@ -521,7 +528,7 @@ Name SExpressionWasmBuilder::getMemoryName(Element& s) { return s.str(); } else { // index - size_t offset = atoi(s.str().c_str()); + size_t offset = parseIndex(s); return getMemoryNameAtIdx(offset); } } @@ -531,7 +538,7 @@ Name SExpressionWasmBuilder::getGlobalName(Element& s) { return s.str(); } else { // index - size_t offset = atoi(s.str().c_str()); + size_t offset = parseIndex(s); if (offset >= globalNames.size()) { throw ParseException("unknown global in getGlobalName", s.line, s.col); } @@ -544,7 +551,7 @@ Name SExpressionWasmBuilder::getTagName(Element& s) { return s.str(); } else { // index - size_t offset = atoi(s.str().c_str()); + size_t offset = parseIndex(s); if (offset >= tagNames.size()) { throw ParseException("unknown tag in getTagName", s.line, s.col); } @@ -738,7 +745,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { size_t numTypes = 0; forEachType([&](Element& elem, size_t) { if (elem[1]->dollared()) { - std::string name = elem[1]->c_str(); + std::string name = elem[1]->toString(); if (!typeIndices.insert({name, numTypes}).second) { throw ParseException("duplicate function type", elem.line, elem.col); } @@ -769,23 +776,23 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { auto nullable = elem[1]->isStr() && *elem[1] == NULL_ ? Nullable : NonNullable; auto& referent = nullable ? *elem[2] : *elem[1]; - const char* name = referent.c_str(); + auto name = referent.toString(); if (referent.dollared()) { return builder.getTempRefType(builder[typeIndices[name]], nullable); } else if (String::isNumber(name)) { - size_t index = atoi(name); + size_t index = parseIndex(referent); if (index >= numTypes) { throw ParseException("invalid type index", elem.line, elem.col); } return builder.getTempRefType(builder[index], nullable); } else { - return Type(stringToHeapType(name), nullable); + return Type(stringToHeapType(referent.str()), nullable); } }; auto parseValType = [&](Element& elem) { if (elem.isStr()) { - return stringToType(elem.c_str()); + return stringToType(elem.str()); } else if (*elem[0] == REF) { return parseRefType(elem); } else { @@ -921,7 +928,7 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { super = extends[1]; } if (super) { - auto it = typeIndices.find(super->c_str()); + auto it = typeIndices.find(super->toString()); if (it == typeIndices.end()) { throw ParseException("unknown supertype", super->line, super->col); } @@ -1139,135 +1146,124 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { nameMapper.clear(); } -Type SExpressionWasmBuilder::stringToType(const char* str, +Type SExpressionWasmBuilder::stringToType(std::string_view str, bool allowError, bool prefix) { - if (str[0] == 'i') { - if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0)) { - return Type::i32; - } - if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0)) { - return Type::i64; - } - } - if (str[0] == 'f') { - if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0)) { - return Type::f32; + if (str.size() >= 3) { + if (str[0] == 'i') { + if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0)) { + return Type::i32; + } + if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0)) { + return Type::i64; + } } - if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0)) { - return Type::f64; + if (str[0] == 'f') { + if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0)) { + return Type::f32; + } + if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0)) { + return Type::f64; + } } } - if (str[0] == 'v') { - if (str[1] == '1' && str[2] == '2' && str[3] == '8' && - (prefix || str[4] == 0)) { - return Type::v128; + if (str.size() >= 4) { + if (str[0] == 'v') { + if (str[1] == '1' && str[2] == '2' && str[3] == '8' && + (prefix || str[4] == 0)) { + return Type::v128; + } } } - if (strncmp(str, "funcref", 7) == 0 && (prefix || str[7] == 0)) { + if (str.substr(0, 7) == "funcref" && (prefix || str.size() == 7)) { return Type(HeapType::func, Nullable); } - if (strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) { + if (str.substr(0, 9) == "externref" && (prefix || str.size() == 9)) { return Type(HeapType::ext, Nullable); } - if (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0)) { + if (str.substr(0, 6) == "anyref" && (prefix || str.size() == 6)) { return Type(HeapType::any, Nullable); } - if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) { + if (str.substr(0, 5) == "eqref" && (prefix || str.size() == 5)) { return Type(HeapType::eq, Nullable); } - if (strncmp(str, "i31ref", 6) == 0 && (prefix || str[6] == 0)) { + if (str.substr(0, 6) == "i31ref" && (prefix || str.size() == 6)) { return Type(HeapType::i31, Nullable); } - if (strncmp(str, "dataref", 7) == 0 && (prefix || str[7] == 0)) { + if (str.substr(0, 7) == "dataref" && (prefix || str.size() == 7)) { return Type(HeapType::data, Nullable); } - if (strncmp(str, "stringref", 9) == 0 && (prefix || str[9] == 0)) { + if (str.substr(0, 9) == "stringref" && (prefix || str.size() == 9)) { return Type(HeapType::string, Nullable); } - if (strncmp(str, "stringview_wtf8", 15) == 0 && (prefix || str[15] == 0)) { + if (str.substr(0, 15) == "stringview_wtf8" && (prefix || str.size() == 15)) { return Type(HeapType::stringview_wtf8, Nullable); } - if (strncmp(str, "stringview_wtf16", 16) == 0 && (prefix || str[16] == 0)) { + if (str.substr(0, 16) == "stringview_wtf16" && (prefix || str.size() == 16)) { return Type(HeapType::stringview_wtf16, Nullable); } - if (strncmp(str, "stringview_iter", 15) == 0 && (prefix || str[15] == 0)) { + if (str.substr(0, 15) == "stringview_iter" && (prefix || str.size() == 15)) { return Type(HeapType::stringview_iter, Nullable); } - if (strncmp(str, "nullref", 7) == 0 && (prefix || str[7] == 0)) { + if (str.substr(0, 7) == "nullref" && (prefix || str.size() == 7)) { return Type(HeapType::none, Nullable); } - if (strncmp(str, "nullexternref", 13) == 0 && (prefix || str[13] == 0)) { + if (str.substr(0, 13) == "nullexternref" && (prefix || str.size() == 13)) { return Type(HeapType::noext, Nullable); } - if (strncmp(str, "nullfuncref", 11) == 0 && (prefix || str[11] == 0)) { + if (str.substr(0, 11) == "nullfuncref" && (prefix || str.size() == 11)) { return Type(HeapType::nofunc, Nullable); } if (allowError) { return Type::none; } - throw ParseException(std::string("invalid wasm type: ") + str); + throw ParseException(std::string("invalid wasm type: ") + + std::string(str.data(), str.size())); } -HeapType SExpressionWasmBuilder::stringToHeapType(const char* str, +HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str, bool prefix) { - if (str[0] == 'f') { - if (str[1] == 'u' && str[2] == 'n' && str[3] == 'c' && - (prefix || str[4] == 0)) { - return HeapType::func; - } + if (str.substr(0, 4) == "func" && (prefix || str.size() == 4)) { + return HeapType::func; } - if (str[0] == 'e') { - if (str[1] == 'q' && (prefix || str[2] == 0)) { - return HeapType::eq; - } - if (str[1] == 'x' && str[2] == 't' && str[3] == 'e' && str[4] == 'r' && - str[5] == 'n' && (prefix || str[6] == 0)) { - return HeapType::ext; - } + if (str.substr(0, 2) == "eq" && (prefix || str.size() == 2)) { + return HeapType::eq; } - if (str[0] == 'a') { - if (str[1] == 'n' && str[2] == 'y' && (prefix || str[3] == 0)) { - return HeapType::any; - } + if (str.substr(0, 6) == "extern" && (prefix || str.size() == 6)) { + return HeapType::ext; } - if (str[0] == 'i') { - if (str[1] == '3' && str[2] == '1' && (prefix || str[3] == 0)) { - return HeapType::i31; - } + if (str.substr(0, 3) == "any" && (prefix || str.size() == 3)) { + return HeapType::any; } - if (str[0] == 'd') { - if (str[1] == 'a' && str[2] == 't' && str[3] == 'a' && - (prefix || str[4] == 0)) { - return HeapType::data; - } + if (str.substr(0, 3) == "i31" && (prefix || str.size() == 3)) { + return HeapType::i31; } - if (str[0] == 's') { - if (strncmp(str, "string", 6) == 0 && (prefix || str[6] == 0)) { - return HeapType::string; - } - if (strncmp(str, "stringview_wtf8", 15) == 0 && (prefix || str[15] == 0)) { - return HeapType::stringview_wtf8; - } - if (strncmp(str, "stringview_wtf16", 16) == 0 && (prefix || str[16] == 0)) { - return HeapType::stringview_wtf16; - } - if (strncmp(str, "stringview_iter", 15) == 0 && (prefix || str[15] == 0)) { - return HeapType::stringview_iter; - } + if (str.substr(0, 4) == "data" && (prefix || str.size() == 4)) { + return HeapType::data; } - if (str[0] == 'n') { - if (strncmp(str, "none", 4) == 0 && (prefix || str[4] == 0)) { - return HeapType::none; - } - if (strncmp(str, "noextern", 8) == 0 && (prefix || str[8] == 0)) { - return HeapType::noext; - } - if (strncmp(str, "nofunc", 6) == 0 && (prefix || str[6] == 0)) { - return HeapType::nofunc; - } + if (str.substr(0, 6) == "string" && (prefix || str.size() == 6)) { + return HeapType::string; + } + if (str.substr(0, 15) == "stringview_wtf8" && (prefix || str.size() == 15)) { + return HeapType::stringview_wtf8; + } + if (str.substr(0, 16) == "stringview_wtf16" && (prefix || str.size() == 16)) { + return HeapType::stringview_wtf16; } - throw ParseException(std::string("invalid wasm heap type: ") + str); + if (str.substr(0, 15) == "stringview_iter" && (prefix || str.size() == 15)) { + return HeapType::stringview_iter; + } + 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; + } + throw ParseException(std::string("invalid wasm heap type: ") + + std::string(str.data(), str.size())); } Type SExpressionWasmBuilder::elementToType(Element& s) { @@ -1345,7 +1341,7 @@ SExpressionWasmBuilder::getDebugLocation(const SourceLocation& loc) { auto iter = debugInfoFileIndices.find(file); if (iter == debugInfoFileIndices.end()) { Index index = debugInfoFileNames.size(); - debugInfoFileNames.push_back(file.c_str()); + debugInfoFileNames.push_back(file.toString()); debugInfoFileIndices[file] = index; } uint32_t fileIndex = debugInfoFileIndices[file]; @@ -1457,7 +1453,7 @@ Index SExpressionWasmBuilder::getLocalIndex(Element& s) { return currFunction->getLocalIndex(ret); } // this is a numeric index - Index ret = atoi(s.c_str()); + Index ret = parseIndex(s); if (ret >= currFunction->getNumLocals()) { throw ParseException("bad local index", s.line, s.col); } @@ -1620,7 +1616,7 @@ Expression* SExpressionWasmBuilder::makeThenOrElse(Element& s) { } static Expression* parseConst(IString s, Type type, MixedArena& allocator) { - const char* str = s.str; + const char* str = s.str.data(); auto ret = allocator.alloc<Const>(); ret->type = type; if (type.isFloat()) { @@ -1635,7 +1631,6 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { default: return nullptr; } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; return ret; } if (s == NEG_INFINITY) { @@ -1649,7 +1644,6 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { default: return nullptr; } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; return ret; } if (s == _NAN) { @@ -1663,7 +1657,6 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { default: return nullptr; } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; return ret; } bool negative = str[0] == '-'; @@ -1813,7 +1806,6 @@ static Expression* parseConst(IString s, Type type, MixedArena& allocator) { if (ret->value.type != type) { throw ParseException("parsed type does not match expected type"); } - // std::cerr << "make constant " << str << " ==> " << ret->value << '\n'; return ret; } @@ -1842,7 +1834,7 @@ Expression* SExpressionWasmBuilder::makeConst(Element& s, Type type) { } auto ret = allocator.alloc<Const>(); - Type lane_t = stringToLaneType(s[1]->str().str); + Type lane_t = stringToLaneType(s[1]->str().str.data()); size_t lanes = s.size() - 2; switch (lanes) { case 2: { @@ -1918,7 +1910,7 @@ static size_t parseMemAttributes(size_t i, align = fallbackAlign; // Parse "align=X" and "offset=X" arguments, bailing out on anything else. while (!s[i]->isList()) { - const char* str = s[i]->c_str(); + const char* str = s[i]->str().str.data(); if (strncmp(str, "align", 5) != 0 && strncmp(str, "offset", 6) != 0) { return i; } @@ -1957,7 +1949,7 @@ static size_t parseMemAttributes(size_t i, } static const char* findMemExtra(const Element& s, size_t skip, bool isAtomic) { - auto* str = s.c_str(); + auto* str = s.str().str.data(); auto size = strlen(str); auto* ret = strchr(str, '.'); if (!ret) { @@ -1977,8 +1969,8 @@ bool SExpressionWasmBuilder::hasMemoryIdx(Element& s, Index defaultSize, Index i) { if (s.size() > defaultSize && !s[i]->isList() && - strncmp(s[i]->c_str(), "align", 5) != 0 && - strncmp(s[i]->c_str(), "offset", 6) != 0) { + strncmp(s[i]->str().str.data(), "align", 5) != 0 && + strncmp(s[i]->str().str.data(), "offset", 6) != 0) { return true; } return false; @@ -2190,7 +2182,7 @@ Expression* SExpressionWasmBuilder::makeAtomicFence(Element& s) { } static uint8_t parseLaneIndex(const Element* s, size_t lanes) { - const char* str = s->c_str(); + const char* str = s->str().str.data(); char* end; auto n = static_cast<unsigned long long>(strtoll(str, &end, 10)); if (end == str || *end != '\0') { @@ -2360,7 +2352,7 @@ Expression* SExpressionWasmBuilder::makeMemoryInit(Element& s) { memory = getMemoryNameAtIdx(0); } ret->memory = memory; - ret->segment = atoi(s[i++]->str().c_str()); + ret->segment = parseIndex(*s[i++]); ret->dest = parseExpression(s[i++]); ret->offset = parseExpression(s[i++]); ret->size = parseExpression(s[i]); @@ -2370,7 +2362,7 @@ Expression* SExpressionWasmBuilder::makeMemoryInit(Element& s) { Expression* SExpressionWasmBuilder::makeDataDrop(Element& s) { auto ret = allocator.alloc<DataDrop>(); - ret->segment = atoi(s[1]->str().c_str()); + ret->segment = parseIndex(*s[1]); ret->finalize(); return ret; } @@ -2552,7 +2544,7 @@ Name SExpressionWasmBuilder::getLabel(Element& s, LabelType labelType) { // offset, break to nth outside label uint64_t offset; try { - offset = std::stoll(s.c_str(), nullptr, 0); + offset = std::stoll(s.toString(), nullptr, 0); } catch (std::invalid_argument&) { throw ParseException("invalid break offset", s.line, s.col); } catch (std::out_of_range&) { @@ -2836,7 +2828,7 @@ Expression* SExpressionWasmBuilder::makeTupleMake(Element& s) { Expression* SExpressionWasmBuilder::makeTupleExtract(Element& s) { auto ret = allocator.alloc<TupleExtract>(); - ret->index = atoi(s[1]->str().c_str()); + ret->index = parseIndex(*s[1]); ret->tuple = parseExpression(s[2]); if (ret->tuple->type != Type::unreachable && ret->index >= ret->tuple->type.size()) { @@ -2943,7 +2935,7 @@ Expression* SExpressionWasmBuilder::makeStructNewStatic(Element& s, Index SExpressionWasmBuilder::getStructIndex(Element& type, Element& field) { if (field.dollared()) { auto name = field.str(); - auto index = typeIndices[type.str().str]; + auto index = typeIndices[type.toString()]; auto struct_ = types[index].getStruct(); auto& fields = struct_.fields; const auto& names = fieldNames[index]; @@ -2956,7 +2948,7 @@ Index SExpressionWasmBuilder::getStructIndex(Element& type, Element& field) { throw ParseException("bad struct field name", field.line, field.col); } // this is a numeric index - return atoi(field.c_str()); + return parseIndex(field); } Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) { @@ -3055,12 +3047,12 @@ Expression* SExpressionWasmBuilder::makeStringNew(Element& s, StringNewOp op) { size_t i = 1; Expression* length = nullptr; if (op == StringNewWTF8) { - const char* str = s[i++]->c_str(); - if (strncmp(str, "utf8", 4) == 0) { + std::string_view str = s[i++]->str().str; + if (str == "utf8") { op = StringNewUTF8; - } else if (strncmp(str, "wtf8", 4) == 0) { + } else if (str == "wtf8") { op = StringNewWTF8; - } else if (strncmp(str, "replace", 7) == 0) { + } else if (str == "replace") { op = StringNewReplace; } else { throw ParseException("bad string.new op", s.line, s.col); @@ -3071,12 +3063,12 @@ Expression* SExpressionWasmBuilder::makeStringNew(Element& s, StringNewOp op) { length = parseExpression(s[i + 1]); return Builder(wasm).makeStringNew(op, parseExpression(s[i]), length); } else if (op == StringNewWTF8Array) { - const char* str = s[i++]->c_str(); - if (strncmp(str, "utf8", 4) == 0) { + std::string_view str = s[i++]->str().str; + if (str == "utf8") { op = StringNewUTF8Array; - } else if (strncmp(str, "wtf8", 4) == 0) { + } else if (str == "wtf8") { op = StringNewWTF8Array; - } else if (strncmp(str, "replace", 7) == 0) { + } else if (str == "replace") { op = StringNewReplaceArray; } else { throw ParseException("bad string.new op", s.line, s.col); @@ -3094,16 +3086,9 @@ Expression* SExpressionWasmBuilder::makeStringNew(Element& s, StringNewOp op) { } Expression* SExpressionWasmBuilder::makeStringConst(Element& s) { - Name rawStr = s[1]->str(); - size_t len = rawStr.size(); std::vector<char> data; - stringToBinary(rawStr.c_str(), len, data); - data.push_back('\0'); - Name str = data.empty() ? "" : &data[0]; - if (str.size() != data.size() - 1) { - throw ParseException( - "zero bytes not yet supported in string constants", s.line, s.col); - } + stringToBinary(*s[1], s[1]->str().str, data); + Name str = std::string_view(data.data(), data.size()); return Builder(wasm).makeStringConst(str); } @@ -3111,10 +3096,10 @@ Expression* SExpressionWasmBuilder::makeStringMeasure(Element& s, StringMeasureOp op) { size_t i = 1; if (op == StringMeasureWTF8) { - const char* str = s[i++]->c_str(); - if (strncmp(str, "utf8", 4) == 0) { + std::string_view str = s[i++]->str().str; + if (str == "utf8") { op = StringMeasureUTF8; - } else if (strncmp(str, "wtf8", 4) == 0) { + } else if (str == "wtf8") { op = StringMeasureWTF8; } else { throw ParseException("bad string.measure op", s.line, s.col); @@ -3128,19 +3113,19 @@ Expression* SExpressionWasmBuilder::makeStringEncode(Element& s, size_t i = 1; Expression* start = nullptr; if (op == StringEncodeWTF8) { - const char* str = s[i++]->c_str(); - if (strncmp(str, "utf8", 4) == 0) { + std::string_view str = s[i++]->str().str; + if (str == "utf8") { op = StringEncodeUTF8; - } else if (strncmp(str, "wtf8", 4) == 0) { + } else if (str == "wtf8") { op = StringEncodeWTF8; } else { throw ParseException("bad string.new op", s.line, s.col); } } else if (op == StringEncodeWTF8Array) { - const char* str = s[i++]->c_str(); - if (strncmp(str, "utf8", 4) == 0) { + std::string_view str = s[i++]->str().str; + if (str == "utf8") { op = StringEncodeUTF8Array; - } else if (strncmp(str, "wtf8", 4) == 0) { + } else if (str == "wtf8") { op = StringEncodeWTF8Array; } else { throw ParseException("bad string.new op", s.line, s.col); @@ -3201,17 +3186,18 @@ Expression* SExpressionWasmBuilder::makeStringSliceIter(Element& s) { // converts an s-expression string representing binary data into an output // sequence of raw bytes this appends to data, which may already contain // content. -void SExpressionWasmBuilder::stringToBinary(const char* input, - size_t size, +void SExpressionWasmBuilder::stringToBinary(Element& s, + std::string_view str, std::vector<char>& data) { auto originalSize = data.size(); - data.resize(originalSize + size); + data.resize(originalSize + str.size()); char* write = data.data() + originalSize; - while (1) { - if (input[0] == 0) { - break; - } + const char* end = str.data() + str.size(); + for (const char* input = str.data(); input < end;) { if (input[0] == '\\') { + if (input + 1 >= end) { + throw ParseException("Unterminated escape sequence", s.line, s.col); + } if (input[1] == 't') { *write++ = '\t'; input += 2; @@ -3237,6 +3223,9 @@ void SExpressionWasmBuilder::stringToBinary(const char* input, input += 2; continue; } else { + if (input + 2 >= end) { + throw ParseException("Unterminated escape sequence", s.line, s.col); + } *write++ = (char)(unhex(input[1]) * 16 + unhex(input[2])); input += 3; continue; @@ -3361,7 +3350,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { checkAddress(offsetValue, "excessive memory offset", offsetElem); } } - const char* input = curr[j]->c_str(); + std::string_view input = curr[j]->str().str; auto* offset = allocator.alloc<Const>(); if (memory->is64()) { offset->type = Type::i64; @@ -3370,9 +3359,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { offset->type = Type::i32; offset->value = Literal(int32_t(offsetValue)); } - if (auto size = strlen(input)) { + if (input.size()) { std::vector<char> data; - stringToBinary(input, size, data); + stringToBinary(*curr[j], input, data); auto segment = Builder::makeDataSegment(Name::fromInt(dataCounter++), memory->name, false, @@ -3437,10 +3426,8 @@ void SExpressionWasmBuilder::parseInnerData(Element& s, std::unique_ptr<DataSegment>& seg) { std::vector<char> data; while (i < s.size()) { - const char* input = s[i++]->c_str(); - if (auto size = strlen(input)) { - stringToBinary(input, size, data); - } + std::string_view input = s[i++]->str().str; + stringToBinary(s, input, data); } seg->data.resize(data.size()); std::copy_n(data.data(), data.size(), seg->data.begin()); @@ -3736,12 +3723,12 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) { bool hasExplicitLimit = false; - if (s[i]->isStr() && String::isNumber(s[i]->c_str())) { - table->initial = atoi(s[i++]->c_str()); + if (s[i]->isStr() && String::isNumber(s[i]->toString())) { + table->initial = parseIndex(*s[i++]); hasExplicitLimit = true; } - if (s[i]->isStr() && String::isNumber(s[i]->c_str())) { - table->max = atoi(s[i++]->c_str()); + if (s[i]->isStr() && String::isNumber(s[i]->toString())) { + table->max = parseIndex(*s[i++]); } table->type = elementToType(*s[i++]); @@ -3905,7 +3892,7 @@ HeapType SExpressionWasmBuilder::parseHeapType(Element& s) { if (s.isStr()) { // It's a string. if (s.dollared()) { - auto it = typeIndices.find(s.str().str); + auto it = typeIndices.find(s.toString()); if (it == typeIndices.end()) { throw ParseException("unknown dollared function type", s.line, s.col); } @@ -3913,15 +3900,15 @@ HeapType SExpressionWasmBuilder::parseHeapType(Element& s) { } else { // It may be a numerical index, or it may be a built-in type name like // "i31". - auto* str = s.str().c_str(); + auto str = s.toString(); if (String::isNumber(str)) { - size_t offset = atoi(str); + size_t offset = parseIndex(s); if (offset >= types.size()) { throw ParseException("unknown indexed function type", s.line, s.col); } return types[offset]; } - return stringToHeapType(str, /* prefix = */ false); + return stringToHeapType(s.str(), /* prefix = */ false); } } throw ParseException("invalid heap type", s.line, s.col); diff --git a/src/wasm2js.h b/src/wasm2js.h index ceae32eb9..2ae22de09 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -230,7 +230,7 @@ public: // First up check our cached of mangled names to avoid doing extra work // below auto& map = wasmNameToMangledName[(int)scope]; - auto it = map.find(name.c_str()); + auto it = map.find(name.str.data()); if (it != map.end()) { return it->second; } @@ -249,7 +249,7 @@ public: IString ret; for (int i = 0;; i++) { std::ostringstream out; - out << name.c_str(); + out << name; if (i > 0) { out << "_" << i; } @@ -276,7 +276,7 @@ public: } // We found a good name, use it. scopeMangledNames.insert(ret); - map[name.c_str()] = ret; + map[name.str.data()] = ret; return ret; } } @@ -586,7 +586,7 @@ void Wasm2JSBuilder::addBasics(Ref ast, Module* wasm) { } static bool needsQuoting(Name name) { - auto mangled = asmangle(name.str); + auto mangled = asmangle(name.toString()); return mangled != name.str; } @@ -717,7 +717,7 @@ void Wasm2JSBuilder::addTable(Ref ast, Module* wasm) { } else if (auto* get = offset->dynCast<GlobalGet>()) { index = ValueBuilder::makeBinary( ValueBuilder::makeName( - stringToIString(asmangle(get->name.str))), + stringToIString(asmangle(get->name.toString()))), PLUS, ValueBuilder::makeNum(i)); } else { @@ -807,7 +807,7 @@ void Wasm2JSBuilder::addExports(Ref ast, Module* wasm) { // setter { std::ostringstream buffer; - buffer << '_' << identName.c_str(); + buffer << '_' << identName; auto setterParam = stringToIString(buffer.str()); auto block = ValueBuilder::makeBlock(); @@ -2615,8 +2615,8 @@ void Wasm2JSGlue::emitPreES6() { } baseModuleMap[base] = module; if (seenModules.count(module) == 0) { - out << "import * as " << asmangle(module.str) << " from '" << module.str - << "';\n"; + out << "import * as " << asmangle(module.toString()) << " from '" + << module << "';\n"; seenModules.insert(module); } }; @@ -2678,8 +2678,8 @@ void Wasm2JSGlue::emitPostES6() { if (seenModules.count(import->module) > 0) { return; } - out << " \"" << import->module << "\": " << asmangle(import->module.str) - << ",\n"; + out << " \"" << import->module + << "\": " << asmangle(import->module.toString()) << ",\n"; seenModules.insert(import->module); }); @@ -2690,7 +2690,7 @@ void Wasm2JSGlue::emitPostES6() { return; } out << " \"" << import->module << "\": {\n"; - out << " " << asmangle(import->base.str) << ": { buffer : mem" + out << " " << asmangle(import->base.toString()) << ": { buffer : mem" << moduleName.str << " }\n"; out << " },\n"; }); @@ -2704,8 +2704,8 @@ void Wasm2JSGlue::emitPostES6() { if (seenModules.count(import->module) > 0) { return; } - out << " \"" << import->module << "\": " << asmangle(import->module.str) - << ",\n"; + out << " \"" << import->module + << "\": " << asmangle(import->module.toString()) << ",\n"; seenModules.insert(import->module); }); @@ -2729,15 +2729,15 @@ void Wasm2JSGlue::emitPostES6() { continue; } std::ostringstream export_name; - for (auto* ptr = exp->name.str; *ptr; ptr++) { - if (*ptr == '-') { + for (char c : exp->name.str) { + if (c == '-') { export_name << '_'; } else { - export_name << *ptr; + export_name << c; } } - out << "export var " << asmangle(exp->name.str) << " = ret" - << moduleName.str << "." << asmangle(exp->name.str) << ";\n"; + out << "export var " << asmangle(exp->name.toString()) << " = ret" + << moduleName << "." << asmangle(exp->name.toString()) << ";\n"; } } @@ -2816,8 +2816,8 @@ void Wasm2JSGlue::emitMemory() { if (auto* get = segment.offset->dynCast<GlobalGet>()) { auto internalName = get->name; auto importedGlobal = wasm.getGlobal(internalName); - return std::string("imports['") + importedGlobal->module.str + "']['" + - importedGlobal->base.str + "']"; + return std::string("imports['") + importedGlobal->module.toString() + + "']['" + importedGlobal->base.toString() + "']"; } Fatal() << "non-constant offsets aren't supported yet\n"; }; diff --git a/test/spec/old_select.wast b/test/spec/old_select.wast index 5228017b0..e6a7ed6a4 100644 --- a/test/spec/old_select.wast +++ b/test/spec/old_select.wast @@ -93,8 +93,8 @@ (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan)) (assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304)) -(assert_return (invoke "select-funcref" (ref.func "dummy") (ref.null func) (i32.const 1)) (ref.func "dummy")) -(assert_return (invoke "select-funcref" (ref.func "dummy") (ref.null func) (i32.const 0)) (ref.null func)) +(assert_return (invoke "select-funcref" (ref.func $dummy) (ref.null func) (i32.const 1)) (ref.func $dummy)) +(assert_return (invoke "select-funcref" (ref.func $dummy) (ref.null func) (i32.const 0)) (ref.null func)) (assert_return (invoke "select-externref" (ref.null extern) (ref.null extern) (i32.const 1)) (ref.null extern)) (assert_return (invoke "select-externref" (ref.null extern) (ref.null extern) (i32.const 0)) (ref.null extern)) |