summaryrefslogtreecommitdiffstats
path: root/third_party/wasm2c/include
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/wasm2c/include
parentInitial commit. (diff)
downloadfirefox-esr-upstream.tar.xz
firefox-esr-upstream.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/wasm2c/include')
-rw-r--r--third_party/wasm2c/include/wabt/apply-names.h45
-rw-r--r--third_party/wasm2c/include/wabt/base-types.h35
-rw-r--r--third_party/wasm2c/include/wabt/binary-reader-ir.h37
-rw-r--r--third_party/wasm2c/include/wabt/binary-reader-logging.h424
-rw-r--r--third_party/wasm2c/include/wabt/binary-reader-nop.h589
-rw-r--r--third_party/wasm2c/include/wabt/binary-reader-objdump.h98
-rw-r--r--third_party/wasm2c/include/wabt/binary-reader-opcnt.h96
-rw-r--r--third_party/wasm2c/include/wabt/binary-reader.h505
-rw-r--r--third_party/wasm2c/include/wabt/binary-writer-spec.h60
-rw-r--r--third_party/wasm2c/include/wabt/binary-writer.h62
-rw-r--r--third_party/wasm2c/include/wabt/binary.h106
-rw-r--r--third_party/wasm2c/include/wabt/binding-hash.h72
-rw-r--r--third_party/wasm2c/include/wabt/c-writer.h59
-rw-r--r--third_party/wasm2c/include/wabt/cast.h109
-rw-r--r--third_party/wasm2c/include/wabt/circular-array.h123
-rw-r--r--third_party/wasm2c/include/wabt/color.h72
-rw-r--r--third_party/wasm2c/include/wabt/common.h456
-rw-r--r--third_party/wasm2c/include/wabt/decompiler-ast.h406
-rw-r--r--third_party/wasm2c/include/wabt/decompiler-ls.h267
-rw-r--r--third_party/wasm2c/include/wabt/decompiler-naming.h205
-rw-r--r--third_party/wasm2c/include/wabt/decompiler.h35
-rw-r--r--third_party/wasm2c/include/wabt/error-formatter.h54
-rw-r--r--third_party/wasm2c/include/wabt/error.h58
-rw-r--r--third_party/wasm2c/include/wabt/expr-visitor.h222
-rw-r--r--third_party/wasm2c/include/wabt/feature.def42
-rw-r--r--third_party/wasm2c/include/wabt/feature.h58
-rw-r--r--third_party/wasm2c/include/wabt/filenames.h51
-rw-r--r--third_party/wasm2c/include/wabt/generate-names.h46
-rw-r--r--third_party/wasm2c/include/wabt/intrusive-list.h631
-rw-r--r--third_party/wasm2c/include/wabt/ir-util.h77
-rw-r--r--third_party/wasm2c/include/wabt/ir.h1483
-rw-r--r--third_party/wasm2c/include/wabt/leb128.h70
-rw-r--r--third_party/wasm2c/include/wabt/lexer-source-line-finder.h61
-rw-r--r--third_party/wasm2c/include/wabt/lexer-source.h53
-rw-r--r--third_party/wasm2c/include/wabt/literal.h129
-rw-r--r--third_party/wasm2c/include/wabt/opcode-code-table.h43
-rw-r--r--third_party/wasm2c/include/wabt/opcode.def593
-rw-r--r--third_party/wasm2c/include/wabt/opcode.h172
-rw-r--r--third_party/wasm2c/include/wabt/option-parser.h99
-rw-r--r--third_party/wasm2c/include/wabt/range.h37
-rw-r--r--third_party/wasm2c/include/wabt/resolve-names.h33
-rw-r--r--third_party/wasm2c/include/wabt/result.h63
-rw-r--r--third_party/wasm2c/include/wabt/sha256.h31
-rw-r--r--third_party/wasm2c/include/wabt/shared-validator.h330
-rw-r--r--third_party/wasm2c/include/wabt/stream.h229
-rw-r--r--third_party/wasm2c/include/wabt/string-format.h68
-rw-r--r--third_party/wasm2c/include/wabt/string-util.h82
-rw-r--r--third_party/wasm2c/include/wabt/token.def175
-rw-r--r--third_party/wasm2c/include/wabt/token.h134
-rw-r--r--third_party/wasm2c/include/wabt/tracing.h73
-rw-r--r--third_party/wasm2c/include/wabt/type-checker.h207
-rw-r--r--third_party/wasm2c/include/wabt/type.h164
-rw-r--r--third_party/wasm2c/include/wabt/utf8.h28
-rw-r--r--third_party/wasm2c/include/wabt/validator.h36
-rw-r--r--third_party/wasm2c/include/wabt/wast-lexer.h117
-rw-r--r--third_party/wasm2c/include/wabt/wast-parser.h276
-rw-r--r--third_party/wasm2c/include/wabt/wat-writer.h41
57 files changed, 9927 insertions, 0 deletions
diff --git a/third_party/wasm2c/include/wabt/apply-names.h b/third_party/wasm2c/include/wabt/apply-names.h
new file mode 100644
index 0000000000..4d30fbd887
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/apply-names.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_APPLY_NAMES_H_
+#define WABT_APPLY_NAMES_H_
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+struct Module;
+
+/* Use function, import, function type, parameter and local names in Vars
+ * that reference them.
+ *
+ * e.g. transform this:
+ *
+ * (func $foo ...)
+ * ...
+ * (call 0 ...)
+ *
+ * to this:
+ *
+ * (func $foo ...)
+ * ...
+ * (call $foo ...)
+ */
+Result ApplyNames(struct Module*);
+
+} // namespace wabt
+
+#endif /* WABT_APPLY_NAMES_H_ */
diff --git a/third_party/wasm2c/include/wabt/base-types.h b/third_party/wasm2c/include/wabt/base-types.h
new file mode 100644
index 0000000000..9e33835330
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/base-types.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#ifndef WABT_BASE_TYPES_H_
+#define WABT_BASE_TYPES_H_
+
+#include <cstddef>
+#include <cstdint>
+
+namespace wabt {
+
+using Index = uint32_t; // An index into one of the many index spaces.
+using Address = uint64_t; // An address or size in linear memory.
+using Offset = size_t; // An offset into a host's file or memory buffer.
+
+constexpr Address kInvalidAddress = ~0;
+constexpr Index kInvalidIndex = ~0;
+constexpr Offset kInvalidOffset = ~0;
+
+} // namespace wabt
+
+#endif // WABT_BASE_TYPES_H_
diff --git a/third_party/wasm2c/include/wabt/binary-reader-ir.h b/third_party/wasm2c/include/wabt/binary-reader-ir.h
new file mode 100644
index 0000000000..4de0ee7099
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary-reader-ir.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINARY_READER_IR_H_
+#define WABT_BINARY_READER_IR_H_
+
+#include "wabt/common.h"
+#include "wabt/error.h"
+
+namespace wabt {
+
+struct Module;
+struct ReadBinaryOptions;
+
+Result ReadBinaryIr(const char* filename,
+ const void* data,
+ size_t size,
+ const ReadBinaryOptions& options,
+ Errors*,
+ Module* out_module);
+
+} // namespace wabt
+
+#endif /* WABT_BINARY_READER_IR_H_ */
diff --git a/third_party/wasm2c/include/wabt/binary-reader-logging.h b/third_party/wasm2c/include/wabt/binary-reader-logging.h
new file mode 100644
index 0000000000..9ce32aca5e
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary-reader-logging.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_BINARY_READER_LOGGING_H_
+#define WABT_BINARY_READER_LOGGING_H_
+
+#include "wabt/binary-reader.h"
+
+namespace wabt {
+
+class Stream;
+
+class BinaryReaderLogging : public BinaryReaderDelegate {
+ public:
+ BinaryReaderLogging(Stream*, BinaryReaderDelegate* forward);
+
+ bool OnError(const Error&) override;
+ void OnSetState(const State* s) override;
+
+ Result BeginModule(uint32_t version) override;
+ Result EndModule() override;
+
+ Result BeginSection(Index section_index,
+ BinarySection section_type,
+ Offset size) override;
+
+ Result BeginCustomSection(Index section_index,
+ Offset size,
+ std::string_view section_name) override;
+ Result EndCustomSection() override;
+
+ Result BeginTypeSection(Offset size) override;
+ Result OnTypeCount(Index count) override;
+ Result OnFuncType(Index index,
+ Index param_count,
+ Type* param_types,
+ Index result_count,
+ Type* result_types) override;
+ Result OnStructType(Index index, Index field_count, TypeMut* fields) override;
+ Result OnArrayType(Index index, TypeMut field) override;
+ Result EndTypeSection() override;
+
+ Result BeginImportSection(Offset size) override;
+ Result OnImportCount(Index count) override;
+ Result OnImport(Index index,
+ ExternalKind kind,
+ std::string_view module_name,
+ std::string_view field_name) override;
+ Result OnImportFunc(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index func_index,
+ Index sig_index) override;
+ Result OnImportTable(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index table_index,
+ Type elem_type,
+ const Limits* elem_limits) override;
+ Result OnImportMemory(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index memory_index,
+ const Limits* page_limits) override;
+ Result OnImportGlobal(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index global_index,
+ Type type,
+ bool mutable_) override;
+ Result OnImportTag(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index tag_index,
+ Index sig_index) override;
+ Result EndImportSection() override;
+
+ Result BeginFunctionSection(Offset size) override;
+ Result OnFunctionCount(Index count) override;
+ Result OnFunction(Index index, Index sig_index) override;
+ Result EndFunctionSection() override;
+
+ Result BeginTableSection(Offset size) override;
+ Result OnTableCount(Index count) override;
+ Result OnTable(Index index,
+ Type elem_type,
+ const Limits* elem_limits) override;
+ Result EndTableSection() override;
+
+ Result BeginMemorySection(Offset size) override;
+ Result OnMemoryCount(Index count) override;
+ Result OnMemory(Index index, const Limits* limits) override;
+ Result EndMemorySection() override;
+
+ Result BeginGlobalSection(Offset size) override;
+ Result OnGlobalCount(Index count) override;
+ Result BeginGlobal(Index index, Type type, bool mutable_) override;
+ Result BeginGlobalInitExpr(Index index) override;
+ Result EndGlobalInitExpr(Index index) override;
+ Result EndGlobal(Index index) override;
+ Result EndGlobalSection() override;
+
+ Result BeginExportSection(Offset size) override;
+ Result OnExportCount(Index count) override;
+ Result OnExport(Index index,
+ ExternalKind kind,
+ Index item_index,
+ std::string_view name) override;
+ Result EndExportSection() override;
+
+ Result BeginStartSection(Offset size) override;
+ Result OnStartFunction(Index func_index) override;
+ Result EndStartSection() override;
+
+ Result BeginCodeSection(Offset size) override;
+ Result OnFunctionBodyCount(Index count) override;
+ Result BeginFunctionBody(Index index, Offset size) override;
+ Result OnLocalDeclCount(Index count) override;
+ Result OnLocalDecl(Index decl_index, Index count, Type type) override;
+
+ Result OnOpcode(Opcode opcode) override;
+ Result OnOpcodeBare() override;
+ Result OnOpcodeIndex(Index value) override;
+ Result OnOpcodeIndexIndex(Index value, Index value2) override;
+ Result OnOpcodeUint32(uint32_t value) override;
+ Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) override;
+ Result OnOpcodeUint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3) override;
+ Result OnOpcodeUint32Uint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3,
+ uint32_t value4) override;
+ Result OnOpcodeUint64(uint64_t value) override;
+ Result OnOpcodeF32(uint32_t value) override;
+ Result OnOpcodeF64(uint64_t value) override;
+ Result OnOpcodeV128(v128 value) override;
+ Result OnOpcodeBlockSig(Type sig_type) override;
+ Result OnOpcodeType(Type type) override;
+ Result OnAtomicLoadExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result OnAtomicStoreExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result OnAtomicRmwExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result OnBinaryExpr(Opcode opcode) override;
+ Result OnBlockExpr(Type sig_type) override;
+ Result OnBrExpr(Index depth) override;
+ Result OnBrIfExpr(Index depth) override;
+ Result OnBrTableExpr(Index num_targets,
+ Index* target_depths,
+ Index default_target_depth) override;
+ Result OnCallExpr(Index func_index) override;
+ Result OnCatchExpr(Index tag_index) override;
+ Result OnCatchAllExpr() override;
+ Result OnCallIndirectExpr(Index sig_index, Index table_index) override;
+ Result OnCallRefExpr() override;
+ Result OnCompareExpr(Opcode opcode) override;
+ Result OnConvertExpr(Opcode opcode) override;
+ Result OnDelegateExpr(Index depth) override;
+ Result OnDropExpr() override;
+ Result OnElseExpr() override;
+ Result OnEndExpr() override;
+ Result OnF32ConstExpr(uint32_t value_bits) override;
+ Result OnF64ConstExpr(uint64_t value_bits) override;
+ Result OnV128ConstExpr(v128 value_bits) override;
+ Result OnGlobalGetExpr(Index global_index) override;
+ Result OnGlobalSetExpr(Index global_index) override;
+ Result OnI32ConstExpr(uint32_t value) override;
+ Result OnI64ConstExpr(uint64_t value) override;
+ Result OnIfExpr(Type sig_type) override;
+ Result OnLoadExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result OnLocalGetExpr(Index local_index) override;
+ Result OnLocalSetExpr(Index local_index) override;
+ Result OnLocalTeeExpr(Index local_index) override;
+ Result OnLoopExpr(Type sig_type) override;
+ Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override;
+ Result OnDataDropExpr(Index segment_index) override;
+ Result OnMemoryFillExpr(Index memidx) override;
+ Result OnMemoryGrowExpr(Index memidx) override;
+ Result OnMemoryInitExpr(Index segment_index, Index memidx) override;
+ Result OnMemorySizeExpr(Index memidx) override;
+ Result OnTableCopyExpr(Index dst_index, Index src_index) override;
+ Result OnElemDropExpr(Index segment_index) override;
+ Result OnTableInitExpr(Index segment_index, Index table_index) override;
+ Result OnTableGetExpr(Index table) override;
+ Result OnTableSetExpr(Index table) override;
+ Result OnTableGrowExpr(Index table) override;
+ Result OnTableSizeExpr(Index table) override;
+ Result OnTableFillExpr(Index table) override;
+ Result OnRefFuncExpr(Index index) override;
+ Result OnRefNullExpr(Type type) override;
+ Result OnRefIsNullExpr() override;
+ Result OnNopExpr() override;
+ Result OnRethrowExpr(Index depth) override;
+ Result OnReturnCallExpr(Index func_index) override;
+ Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override;
+ Result OnReturnExpr() override;
+ Result OnSelectExpr(Index result_count, Type* result_types) override;
+ Result OnStoreExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result OnThrowExpr(Index tag_index) override;
+ Result OnTryExpr(Type sig_type) override;
+ Result OnUnaryExpr(Opcode opcode) override;
+ Result OnTernaryExpr(Opcode opcode) override;
+ Result OnUnreachableExpr() override;
+ Result OnAtomicWaitExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result OnAtomicFenceExpr(uint32_t consistency_model) override;
+ Result OnAtomicNotifyExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result EndFunctionBody(Index index) override;
+ Result EndCodeSection() override;
+ Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override;
+ Result OnSimdLoadLaneExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset,
+ uint64_t value) override;
+ Result OnSimdStoreLaneExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset,
+ uint64_t value) override;
+ Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
+ Result OnLoadSplatExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+ Result OnLoadZeroExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override;
+
+ Result BeginElemSection(Offset size) override;
+ Result OnElemSegmentCount(Index count) override;
+ Result BeginElemSegment(Index index,
+ Index table_index,
+ uint8_t flags) override;
+ Result BeginElemSegmentInitExpr(Index index) override;
+ Result EndElemSegmentInitExpr(Index index) override;
+ Result OnElemSegmentElemType(Index index, Type elem_type) override;
+ Result OnElemSegmentElemExprCount(Index index, Index count) override;
+ Result OnElemSegmentElemExpr_RefNull(Index segment_index, Type type) override;
+ Result OnElemSegmentElemExpr_RefFunc(Index segment_index,
+ Index func_index) override;
+ Result EndElemSegment(Index index) override;
+ Result EndElemSection() override;
+
+ Result BeginDataSection(Offset size) override;
+ Result OnDataSegmentCount(Index count) override;
+ Result BeginDataSegment(Index index,
+ Index memory_index,
+ uint8_t flags) override;
+ Result BeginDataSegmentInitExpr(Index index) override;
+ Result EndDataSegmentInitExpr(Index index) override;
+ Result OnDataSegmentData(Index index,
+ const void* data,
+ Address size) override;
+ Result EndDataSegment(Index index) override;
+ Result EndDataSection() override;
+
+ Result BeginDataCountSection(Offset size) override;
+ Result OnDataCount(Index count) override;
+ Result EndDataCountSection() override;
+
+ Result BeginNamesSection(Offset size) override;
+ Result OnModuleNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) override;
+ Result OnModuleName(std::string_view name) override;
+ Result OnFunctionNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) override;
+ Result OnFunctionNamesCount(Index num_functions) override;
+ Result OnFunctionName(Index function_index,
+ std::string_view function_name) override;
+ Result OnLocalNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) override;
+ Result OnLocalNameFunctionCount(Index num_functions) override;
+ Result OnLocalNameLocalCount(Index function_index, Index num_locals) override;
+ Result OnLocalName(Index function_index,
+ Index local_index,
+ std::string_view local_name) override;
+ Result OnNameSubsection(Index index,
+ NameSectionSubsection subsection_type,
+ Offset subsection_size) override;
+ Result OnNameEntry(NameSectionSubsection type,
+ Index index,
+ std::string_view name) override;
+ Result OnNameCount(Index num_names) override;
+ Result EndNamesSection() override;
+
+ Result BeginRelocSection(Offset size) override;
+ Result OnRelocCount(Index count, Index section_index) override;
+ Result OnReloc(RelocType type,
+ Offset offset,
+ Index index,
+ uint32_t addend) override;
+ Result EndRelocSection() override;
+
+ Result BeginDylinkSection(Offset size) override;
+ Result OnDylinkInfo(uint32_t mem_size,
+ uint32_t mem_align,
+ uint32_t table_size,
+ uint32_t table_align) override;
+ Result OnDylinkNeededCount(Index count) override;
+ Result OnDylinkNeeded(std::string_view needed) override;
+ Result OnDylinkImportCount(Index count) override;
+ Result OnDylinkExportCount(Index count) override;
+ Result OnDylinkImport(std::string_view module,
+ std::string_view name,
+ uint32_t flags) override;
+ Result OnDylinkExport(std::string_view name, uint32_t flags) override;
+ Result EndDylinkSection() override;
+
+ Result BeginTargetFeaturesSection(Offset size) override;
+ Result OnFeatureCount(Index count) override;
+ Result OnFeature(uint8_t prefix, std::string_view name) override;
+ Result EndTargetFeaturesSection() override;
+
+ Result BeginLinkingSection(Offset size) override;
+ Result OnSymbolCount(Index count) override;
+ Result OnDataSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index segment,
+ uint32_t offset,
+ uint32_t size) override;
+ Result OnFunctionSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index func_index) override;
+ Result OnGlobalSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index global_index) override;
+ Result OnSectionSymbol(Index index,
+ uint32_t flags,
+ Index section_index) override;
+ Result OnTagSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index tag_index) override;
+ Result OnTableSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index tag_index) override;
+ Result OnSegmentInfoCount(Index count) override;
+ Result OnSegmentInfo(Index index,
+ std::string_view name,
+ Address alignment,
+ uint32_t flags) override;
+ Result OnInitFunctionCount(Index count) override;
+ Result OnInitFunction(uint32_t priority, Index symbol_index) override;
+ Result OnComdatCount(Index count) override;
+ Result OnComdatBegin(std::string_view name,
+ uint32_t flags,
+ Index count) override;
+ Result OnComdatEntry(ComdatType kind, Index index) override;
+ Result EndLinkingSection() override;
+
+ Result BeginTagSection(Offset size) override;
+ Result OnTagCount(Index count) override;
+ Result OnTagType(Index index, Index sig_index) override;
+ Result EndTagSection() override;
+
+ /* Code Metadata sections */
+ Result BeginCodeMetadataSection(std::string_view name, Offset size) override;
+ Result OnCodeMetadataFuncCount(Index count) override;
+ Result OnCodeMetadataCount(Index function_index, Index count) override;
+ Result OnCodeMetadata(Offset offset, const void* data, Address size) override;
+ Result EndCodeMetadataSection() override;
+
+ private:
+ void Indent();
+ void Dedent();
+ void WriteIndent();
+ void LogType(Type type);
+ void LogTypes(Index type_count, Type* types);
+ void LogTypes(TypeVector& types);
+ void LogField(TypeMut field);
+
+ Stream* stream_;
+ BinaryReaderDelegate* reader_;
+ int indent_;
+};
+
+} // namespace wabt
+
+#endif // WABT_BINARY_READER_LOGGING_H_
diff --git a/third_party/wasm2c/include/wabt/binary-reader-nop.h b/third_party/wasm2c/include/wabt/binary-reader-nop.h
new file mode 100644
index 0000000000..0c9ebc6487
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary-reader-nop.h
@@ -0,0 +1,589 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINARY_READER_NOP_H_
+#define WABT_BINARY_READER_NOP_H_
+
+#include "wabt/binary-reader.h"
+
+namespace wabt {
+
+class BinaryReaderNop : public BinaryReaderDelegate {
+ public:
+ bool OnError(const Error&) override { return false; }
+
+ /* Module */
+ Result BeginModule(uint32_t version) override { return Result::Ok; }
+ Result EndModule() override { return Result::Ok; }
+
+ Result BeginSection(Index section_index,
+ BinarySection section_type,
+ Offset size) override {
+ return Result::Ok;
+ }
+
+ /* Custom section */
+ Result BeginCustomSection(Index section_index,
+ Offset size,
+ std::string_view section_name) override {
+ return Result::Ok;
+ }
+ Result EndCustomSection() override { return Result::Ok; }
+
+ /* Type section */
+ Result BeginTypeSection(Offset size) override { return Result::Ok; }
+ Result OnTypeCount(Index count) override { return Result::Ok; }
+ Result OnFuncType(Index index,
+ Index param_count,
+ Type* param_types,
+ Index result_count,
+ Type* result_types) override {
+ return Result::Ok;
+ }
+ Result OnStructType(Index index,
+ Index field_count,
+ TypeMut* fields) override {
+ return Result::Ok;
+ }
+ Result OnArrayType(Index index, TypeMut field) override { return Result::Ok; }
+ Result EndTypeSection() override { return Result::Ok; }
+
+ /* Import section */
+ Result BeginImportSection(Offset size) override { return Result::Ok; }
+ Result OnImportCount(Index count) override { return Result::Ok; }
+ Result OnImport(Index index,
+ ExternalKind kind,
+ std::string_view module_name,
+ std::string_view field_name) override {
+ return Result::Ok;
+ }
+ Result OnImportFunc(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index func_index,
+ Index sig_index) override {
+ return Result::Ok;
+ }
+ Result OnImportTable(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index table_index,
+ Type elem_type,
+ const Limits* elem_limits) override {
+ return Result::Ok;
+ }
+ Result OnImportMemory(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index memory_index,
+ const Limits* page_limits) override {
+ return Result::Ok;
+ }
+ Result OnImportGlobal(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index global_index,
+ Type type,
+ bool mutable_) override {
+ return Result::Ok;
+ }
+ Result OnImportTag(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index tag_index,
+ Index sig_index) override {
+ return Result::Ok;
+ }
+ Result EndImportSection() override { return Result::Ok; }
+
+ /* Function section */
+ Result BeginFunctionSection(Offset size) override { return Result::Ok; }
+ Result OnFunctionCount(Index count) override { return Result::Ok; }
+ Result OnFunction(Index index, Index sig_index) override {
+ return Result::Ok;
+ }
+ Result EndFunctionSection() override { return Result::Ok; }
+
+ /* Table section */
+ Result BeginTableSection(Offset size) override { return Result::Ok; }
+ Result OnTableCount(Index count) override { return Result::Ok; }
+ Result OnTable(Index index,
+ Type elem_type,
+ const Limits* elem_limits) override {
+ return Result::Ok;
+ }
+ Result EndTableSection() override { return Result::Ok; }
+
+ /* Memory section */
+ Result BeginMemorySection(Offset size) override { return Result::Ok; }
+ Result OnMemoryCount(Index count) override { return Result::Ok; }
+ Result OnMemory(Index index, const Limits* limits) override {
+ return Result::Ok;
+ }
+ Result EndMemorySection() override { return Result::Ok; }
+
+ /* Global section */
+ Result BeginGlobalSection(Offset size) override { return Result::Ok; }
+ Result OnGlobalCount(Index count) override { return Result::Ok; }
+ Result BeginGlobal(Index index, Type type, bool mutable_) override {
+ return Result::Ok;
+ }
+ Result BeginGlobalInitExpr(Index index) override { return Result::Ok; }
+ Result EndGlobalInitExpr(Index index) override { return Result::Ok; }
+ Result EndGlobal(Index index) override { return Result::Ok; }
+ Result EndGlobalSection() override { return Result::Ok; }
+
+ /* Exports section */
+ Result BeginExportSection(Offset size) override { return Result::Ok; }
+ Result OnExportCount(Index count) override { return Result::Ok; }
+ Result OnExport(Index index,
+ ExternalKind kind,
+ Index item_index,
+ std::string_view name) override {
+ return Result::Ok;
+ }
+ Result EndExportSection() override { return Result::Ok; }
+
+ /* Start section */
+ Result BeginStartSection(Offset size) override { return Result::Ok; }
+ Result OnStartFunction(Index func_index) override { return Result::Ok; }
+ Result EndStartSection() override { return Result::Ok; }
+
+ /* Code section */
+ Result BeginCodeSection(Offset size) override { return Result::Ok; }
+ Result OnFunctionBodyCount(Index count) override { return Result::Ok; }
+ Result BeginFunctionBody(Index index, Offset size) override {
+ return Result::Ok;
+ }
+ Result OnLocalDeclCount(Index count) override { return Result::Ok; }
+ Result OnLocalDecl(Index decl_index, Index count, Type type) override {
+ return Result::Ok;
+ }
+
+ /* Function expressions; called between BeginFunctionBody and
+ EndFunctionBody */
+ Result OnOpcode(Opcode Opcode) override { return Result::Ok; }
+ Result OnOpcodeBare() override { return Result::Ok; }
+ Result OnOpcodeIndex(Index value) override { return Result::Ok; }
+ Result OnOpcodeIndexIndex(Index value, Index value2) override {
+ return Result::Ok;
+ }
+ Result OnOpcodeUint32(uint32_t value) override { return Result::Ok; }
+ Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) override {
+ return Result::Ok;
+ }
+ Result OnOpcodeUint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3) override {
+ return Result::Ok;
+ }
+ Result OnOpcodeUint32Uint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3,
+ uint32_t value4) override {
+ return Result::Ok;
+ }
+ Result OnOpcodeUint64(uint64_t value) override { return Result::Ok; }
+ Result OnOpcodeF32(uint32_t value) override { return Result::Ok; }
+ Result OnOpcodeF64(uint64_t value) override { return Result::Ok; }
+ Result OnOpcodeV128(v128 value) override { return Result::Ok; }
+ Result OnOpcodeBlockSig(Type sig_type) override { return Result::Ok; }
+ Result OnOpcodeType(Type type) override { return Result::Ok; }
+ Result OnAtomicLoadExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
+ Result OnAtomicStoreExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
+ Result OnAtomicRmwExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
+ Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
+ Result OnAtomicWaitExpr(Opcode, Index, Address, Address) override {
+ return Result::Ok;
+ }
+ Result OnAtomicFenceExpr(uint32_t) override { return Result::Ok; }
+ Result OnAtomicNotifyExpr(Opcode, Index, Address, Address) override {
+ return Result::Ok;
+ }
+ Result OnBinaryExpr(Opcode opcode) override { return Result::Ok; }
+ Result OnBlockExpr(Type sig_type) override { return Result::Ok; }
+ Result OnBrExpr(Index depth) override { return Result::Ok; }
+ Result OnBrIfExpr(Index depth) override { return Result::Ok; }
+ Result OnBrTableExpr(Index num_targets,
+ Index* target_depths,
+ Index default_target_depth) override {
+ return Result::Ok;
+ }
+ Result OnCallExpr(Index func_index) override { return Result::Ok; }
+ Result OnCallIndirectExpr(Index sig_index, Index table_index) override {
+ return Result::Ok;
+ }
+ Result OnCallRefExpr() override { return Result::Ok; }
+ Result OnCatchExpr(Index tag_index) override { return Result::Ok; }
+ Result OnCatchAllExpr() override { return Result::Ok; }
+ Result OnCompareExpr(Opcode opcode) override { return Result::Ok; }
+ Result OnConvertExpr(Opcode opcode) override { return Result::Ok; }
+ Result OnDelegateExpr(Index depth) override { return Result::Ok; }
+ Result OnDropExpr() override { return Result::Ok; }
+ Result OnElseExpr() override { return Result::Ok; }
+ Result OnEndExpr() override { return Result::Ok; }
+ Result OnF32ConstExpr(uint32_t value_bits) override { return Result::Ok; }
+ Result OnF64ConstExpr(uint64_t value_bits) override { return Result::Ok; }
+ Result OnV128ConstExpr(v128 value_bits) override { return Result::Ok; }
+ Result OnGlobalGetExpr(Index global_index) override { return Result::Ok; }
+ Result OnGlobalSetExpr(Index global_index) override { return Result::Ok; }
+ Result OnI32ConstExpr(uint32_t value) override { return Result::Ok; }
+ Result OnI64ConstExpr(uint64_t value) override { return Result::Ok; }
+ Result OnIfExpr(Type sig_type) override { return Result::Ok; }
+ Result OnLoadExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
+ Result OnLocalGetExpr(Index local_index) override { return Result::Ok; }
+ Result OnLocalSetExpr(Index local_index) override { return Result::Ok; }
+ Result OnLocalTeeExpr(Index local_index) override { return Result::Ok; }
+ Result OnLoopExpr(Type sig_type) override { return Result::Ok; }
+ Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override {
+ return Result::Ok;
+ }
+ Result OnDataDropExpr(Index segment_index) override { return Result::Ok; }
+ Result OnMemoryFillExpr(Index memidx) override { return Result::Ok; }
+ Result OnMemoryGrowExpr(Index memidx) override { return Result::Ok; }
+ Result OnMemoryInitExpr(Index segment_index, Index memidx) override {
+ return Result::Ok;
+ }
+ Result OnMemorySizeExpr(Index memidx) override { return Result::Ok; }
+ Result OnTableCopyExpr(Index dst_index, Index src_index) override {
+ return Result::Ok;
+ }
+ Result OnElemDropExpr(Index segment_index) override { return Result::Ok; }
+ Result OnTableInitExpr(Index segment_index, Index table_index) override {
+ return Result::Ok;
+ }
+ Result OnTableGetExpr(Index table_index) override { return Result::Ok; }
+ Result OnTableSetExpr(Index table_index) override { return Result::Ok; }
+ Result OnTableGrowExpr(Index table_index) override { return Result::Ok; }
+ Result OnTableSizeExpr(Index table_index) override { return Result::Ok; }
+ Result OnTableFillExpr(Index table_index) override { return Result::Ok; }
+ Result OnRefFuncExpr(Index func_index) override { return Result::Ok; }
+ Result OnRefNullExpr(Type type) override { return Result::Ok; }
+ Result OnRefIsNullExpr() override { return Result::Ok; }
+ Result OnNopExpr() override { return Result::Ok; }
+ Result OnRethrowExpr(Index depth) override { return Result::Ok; }
+ Result OnReturnCallExpr(Index sig_index) override { return Result::Ok; }
+ Result OnReturnCallIndirectExpr(Index sig_index, Index table_index) override {
+ return Result::Ok;
+ }
+ Result OnReturnExpr() override { return Result::Ok; }
+ Result OnSelectExpr(Index result_count, Type* result_types) override {
+ return Result::Ok;
+ }
+ Result OnStoreExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
+ Result OnThrowExpr(Index depth) override { return Result::Ok; }
+ Result OnTryExpr(Type sig_type) override { return Result::Ok; }
+ Result OnUnaryExpr(Opcode opcode) override { return Result::Ok; }
+ Result OnTernaryExpr(Opcode opcode) override { return Result::Ok; }
+ Result OnUnreachableExpr() override { return Result::Ok; }
+ Result EndFunctionBody(Index index) override { return Result::Ok; }
+ Result EndCodeSection() override { return Result::Ok; }
+ Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override {
+ return Result::Ok;
+ }
+ Result OnSimdLoadLaneExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset,
+ uint64_t value) override {
+ return Result::Ok;
+ }
+ Result OnSimdStoreLaneExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset,
+ uint64_t value) override {
+ return Result::Ok;
+ }
+ Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override {
+ return Result::Ok;
+ }
+ Result OnLoadSplatExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
+ Result OnLoadZeroExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) override {
+ return Result::Ok;
+ }
+
+ /* Elem section */
+ Result BeginElemSection(Offset size) override { return Result::Ok; }
+ Result OnElemSegmentCount(Index count) override { return Result::Ok; }
+ Result BeginElemSegment(Index index,
+ Index table_index,
+ uint8_t flags) override {
+ return Result::Ok;
+ }
+ Result BeginElemSegmentInitExpr(Index index) override { return Result::Ok; }
+ Result EndElemSegmentInitExpr(Index index) override { return Result::Ok; }
+ Result OnElemSegmentElemType(Index index, Type elem_type) override {
+ return Result::Ok;
+ }
+ Result OnElemSegmentElemExprCount(Index index, Index count) override {
+ return Result::Ok;
+ }
+ Result OnElemSegmentElemExpr_RefNull(Index segment_index,
+ Type type) override {
+ return Result::Ok;
+ }
+ Result OnElemSegmentElemExpr_RefFunc(Index segment_index,
+ Index func_index) override {
+ return Result::Ok;
+ }
+ Result EndElemSegment(Index index) override { return Result::Ok; }
+ Result EndElemSection() override { return Result::Ok; }
+
+ /* Data section */
+ Result BeginDataSection(Offset size) override { return Result::Ok; }
+ Result OnDataSegmentCount(Index count) override { return Result::Ok; }
+ Result BeginDataSegment(Index index,
+ Index memory_index,
+ uint8_t flags) override {
+ return Result::Ok;
+ }
+ Result BeginDataSegmentInitExpr(Index index) override { return Result::Ok; }
+ Result EndDataSegmentInitExpr(Index index) override { return Result::Ok; }
+ Result OnDataSegmentData(Index index,
+ const void* data,
+ Address size) override {
+ return Result::Ok;
+ }
+ Result EndDataSegment(Index index) override { return Result::Ok; }
+ Result EndDataSection() override { return Result::Ok; }
+
+ /* DataCount section */
+ Result BeginDataCountSection(Offset size) override { return Result::Ok; }
+ Result OnDataCount(Index count) override { return Result::Ok; }
+ Result EndDataCountSection() override { return Result::Ok; }
+
+ /* Names section */
+ Result BeginNamesSection(Offset size) override { return Result::Ok; }
+ Result OnModuleNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) override {
+ return Result::Ok;
+ }
+ Result OnModuleName(std::string_view name) override { return Result::Ok; }
+ Result OnFunctionNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) override {
+ return Result::Ok;
+ }
+ Result OnFunctionNamesCount(Index num_functions) override {
+ return Result::Ok;
+ }
+ Result OnFunctionName(Index function_index,
+ std::string_view function_name) override {
+ return Result::Ok;
+ }
+ Result OnLocalNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) override {
+ return Result::Ok;
+ }
+ Result OnLocalNameFunctionCount(Index num_functions) override {
+ return Result::Ok;
+ }
+ Result OnLocalNameLocalCount(Index function_index,
+ Index num_locals) override {
+ return Result::Ok;
+ }
+ Result OnLocalName(Index function_index,
+ Index local_index,
+ std::string_view local_name) override {
+ return Result::Ok;
+ }
+ Result EndNamesSection() override { return Result::Ok; }
+
+ Result OnNameSubsection(Index index,
+ NameSectionSubsection subsection_type,
+ Offset subsection_size) override {
+ return Result::Ok;
+ }
+ Result OnNameCount(Index num_names) override { return Result::Ok; }
+ Result OnNameEntry(NameSectionSubsection type,
+ Index index,
+ std::string_view name) override {
+ return Result::Ok;
+ }
+
+ /* Reloc section */
+ Result BeginRelocSection(Offset size) override { return Result::Ok; }
+ Result OnRelocCount(Index count, Index section_code) override {
+ return Result::Ok;
+ }
+ Result OnReloc(RelocType type,
+ Offset offset,
+ Index index,
+ uint32_t addend) override {
+ return Result::Ok;
+ }
+ Result EndRelocSection() override { return Result::Ok; }
+
+ /* Tag section */
+ Result BeginTagSection(Offset size) override { return Result::Ok; }
+ Result OnTagCount(Index count) override { return Result::Ok; }
+ Result OnTagType(Index index, Index sig_index) override { return Result::Ok; }
+ Result EndTagSection() override { return Result::Ok; }
+
+ /* Code Metadata sections */
+ Result BeginCodeMetadataSection(std::string_view name, Offset size) override {
+ return Result::Ok;
+ }
+ Result OnCodeMetadataFuncCount(Index count) override { return Result::Ok; }
+ Result OnCodeMetadataCount(Index function_index, Index count) override {
+ return Result::Ok;
+ }
+ Result OnCodeMetadata(Offset offset,
+ const void* data,
+ Address size) override {
+ return Result::Ok;
+ }
+ Result EndCodeMetadataSection() override { return Result::Ok; }
+
+ /* Dylink section */
+ Result BeginDylinkSection(Offset size) override { return Result::Ok; }
+ Result OnDylinkInfo(uint32_t mem_size,
+ uint32_t mem_align,
+ uint32_t table_size,
+ uint32_t table_align) override {
+ return Result::Ok;
+ }
+ Result OnDylinkNeededCount(Index count) override { return Result::Ok; }
+ Result OnDylinkNeeded(std::string_view so_name) override {
+ return Result::Ok;
+ }
+ Result OnDylinkImportCount(Index count) override { return Result::Ok; }
+ Result OnDylinkExportCount(Index count) override { return Result::Ok; }
+ Result OnDylinkImport(std::string_view module,
+ std::string_view name,
+ uint32_t flags) override {
+ return Result::Ok;
+ }
+ Result OnDylinkExport(std::string_view name, uint32_t flags) override {
+ return Result::Ok;
+ }
+ Result EndDylinkSection() override { return Result::Ok; }
+
+ /* target_features section */
+ Result BeginTargetFeaturesSection(Offset size) override { return Result::Ok; }
+ Result OnFeatureCount(Index count) override { return Result::Ok; }
+ Result OnFeature(uint8_t prefix, std::string_view name) override {
+ return Result::Ok;
+ }
+ Result EndTargetFeaturesSection() override { return Result::Ok; }
+
+ /* Linking section */
+ Result BeginLinkingSection(Offset size) override { return Result::Ok; }
+ Result OnSymbolCount(Index count) override { return Result::Ok; }
+ Result OnDataSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index segment,
+ uint32_t offset,
+ uint32_t size) override {
+ return Result::Ok;
+ }
+ Result OnFunctionSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index func_index) override {
+ return Result::Ok;
+ }
+ Result OnGlobalSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index global_index) override {
+ return Result::Ok;
+ }
+ Result OnSectionSymbol(Index index,
+ uint32_t flags,
+ Index section_index) override {
+ return Result::Ok;
+ }
+ Result OnTagSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index tag_index) override {
+ return Result::Ok;
+ }
+ Result OnTableSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index table_index) override {
+ return Result::Ok;
+ }
+ Result OnSegmentInfoCount(Index count) override { return Result::Ok; }
+ Result OnSegmentInfo(Index index,
+ std::string_view name,
+ Address alignment,
+ uint32_t flags) override {
+ return Result::Ok;
+ }
+ Result OnInitFunctionCount(Index count) override { return Result::Ok; }
+ Result OnInitFunction(uint32_t priority, Index symbol_index) override {
+ return Result::Ok;
+ }
+ Result OnComdatCount(Index count) override { return Result::Ok; }
+ Result OnComdatBegin(std::string_view name,
+ uint32_t flags,
+ Index count) override {
+ return Result::Ok;
+ }
+ Result OnComdatEntry(ComdatType kind, Index index) override {
+ return Result::Ok;
+ }
+ Result EndLinkingSection() override { return Result::Ok; }
+};
+
+} // namespace wabt
+
+#endif /* WABT_BINARY_READER_H_ */
diff --git a/third_party/wasm2c/include/wabt/binary-reader-objdump.h b/third_party/wasm2c/include/wabt/binary-reader-objdump.h
new file mode 100644
index 0000000000..0ca7458f8e
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary-reader-objdump.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINARY_READER_OBJDUMP_H_
+#define WABT_BINARY_READER_OBJDUMP_H_
+
+#include <map>
+#include <string>
+
+#include "wabt/common.h"
+#include "wabt/feature.h"
+#include "wabt/stream.h"
+
+namespace wabt {
+
+struct Module;
+struct ReadBinaryOptions;
+
+enum class ObjdumpMode {
+ Prepass,
+ Headers,
+ Details,
+ Disassemble,
+ RawData,
+};
+
+struct ObjdumpOptions {
+ Stream* log_stream;
+ bool headers;
+ bool details;
+ bool raw;
+ bool disassemble;
+ bool debug;
+ bool relocs;
+ bool section_offsets;
+ ObjdumpMode mode;
+ const char* filename;
+ const char* section_name;
+};
+
+struct ObjdumpSymbol {
+ wabt::SymbolType kind;
+ std::string name;
+ Index index;
+};
+
+struct ObjdumpNames {
+ std::string_view Get(Index index) const;
+ void Set(Index index, std::string_view name);
+
+ std::map<Index, std::string> names;
+};
+
+struct ObjdumpLocalNames {
+ std::string_view Get(Index function_index, Index local_index) const;
+ void Set(Index function_index, Index local_index, std::string_view name);
+
+ std::map<std::pair<Index, Index>, std::string> names;
+};
+
+// read_binary_objdump uses this state to store information from previous runs
+// and use it to display more useful information.
+struct ObjdumpState {
+ std::vector<Reloc> code_relocations;
+ std::vector<Reloc> data_relocations;
+ ObjdumpNames type_names;
+ ObjdumpNames function_names;
+ ObjdumpNames global_names;
+ ObjdumpNames section_names;
+ ObjdumpNames tag_names;
+ ObjdumpNames segment_names;
+ ObjdumpNames table_names;
+ ObjdumpLocalNames local_names;
+ std::vector<ObjdumpSymbol> symtab;
+ std::map<Index, Index> function_param_counts;
+};
+
+Result ReadBinaryObjdump(const uint8_t* data,
+ size_t size,
+ ObjdumpOptions* options,
+ ObjdumpState* state);
+
+} // namespace wabt
+
+#endif /* WABT_BINARY_READER_OBJDUMP_H_ */
diff --git a/third_party/wasm2c/include/wabt/binary-reader-opcnt.h b/third_party/wasm2c/include/wabt/binary-reader-opcnt.h
new file mode 100644
index 0000000000..8c3a9aba8d
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary-reader-opcnt.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINARY_READER_OPCNT_H_
+#define WABT_BINARY_READER_OPCNT_H_
+
+#include <map>
+#include <vector>
+
+#include "wabt/common.h"
+#include "wabt/opcode.h"
+
+namespace wabt {
+
+struct Module;
+struct ReadBinaryOptions;
+class Stream;
+
+class OpcodeInfo {
+ public:
+ enum class Kind {
+ Bare,
+ Uint32,
+ Uint64,
+ Index,
+ Float32,
+ Float64,
+ Uint32Uint32,
+ Uint32Uint32Uint32,
+ Uint32Uint32Uint32Uint32,
+ BlockSig,
+ BrTable,
+ V128,
+ };
+
+ explicit OpcodeInfo(Opcode, Kind);
+ template <typename T>
+ OpcodeInfo(Opcode, Kind, T* data, size_t count = 1);
+ template <typename T>
+ OpcodeInfo(Opcode, Kind, T* data, size_t count, T extra);
+
+ Opcode opcode() const { return opcode_; }
+
+ void Write(Stream&);
+
+ private:
+ template <typename T>
+ std::pair<const T*, size_t> GetDataArray() const;
+ template <typename T>
+ const T* GetData(size_t expected_size = 1) const;
+
+ template <typename T, typename F>
+ void WriteArray(Stream& stream, F&& write_func);
+
+ Opcode opcode_;
+ Kind kind_;
+ std::vector<uint8_t> data_;
+
+ friend bool operator==(const OpcodeInfo&, const OpcodeInfo&);
+ friend bool operator!=(const OpcodeInfo&, const OpcodeInfo&);
+ friend bool operator<(const OpcodeInfo&, const OpcodeInfo&);
+ friend bool operator<=(const OpcodeInfo&, const OpcodeInfo&);
+ friend bool operator>(const OpcodeInfo&, const OpcodeInfo&);
+ friend bool operator>=(const OpcodeInfo&, const OpcodeInfo&);
+};
+
+bool operator==(const OpcodeInfo&, const OpcodeInfo&);
+bool operator!=(const OpcodeInfo&, const OpcodeInfo&);
+bool operator<(const OpcodeInfo&, const OpcodeInfo&);
+bool operator<=(const OpcodeInfo&, const OpcodeInfo&);
+bool operator>(const OpcodeInfo&, const OpcodeInfo&);
+bool operator>=(const OpcodeInfo&, const OpcodeInfo&);
+
+using OpcodeInfoCounts = std::map<OpcodeInfo, size_t>;
+
+Result ReadBinaryOpcnt(const void* data,
+ size_t size,
+ const ReadBinaryOptions& options,
+ OpcodeInfoCounts* opcode_counts);
+
+} // namespace wabt
+
+#endif /* WABT_BINARY_READER_OPCNT_H_ */
diff --git a/third_party/wasm2c/include/wabt/binary-reader.h b/third_party/wasm2c/include/wabt/binary-reader.h
new file mode 100644
index 0000000000..825d562cb0
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary-reader.h
@@ -0,0 +1,505 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINARY_READER_H_
+#define WABT_BINARY_READER_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <string_view>
+
+#include "wabt/binary.h"
+#include "wabt/common.h"
+#include "wabt/error.h"
+#include "wabt/feature.h"
+#include "wabt/opcode.h"
+
+namespace wabt {
+
+class Stream;
+
+struct ReadBinaryOptions {
+ ReadBinaryOptions() = default;
+ ReadBinaryOptions(const Features& features,
+ Stream* log_stream,
+ bool read_debug_names,
+ bool stop_on_first_error,
+ bool fail_on_custom_section_error)
+ : features(features),
+ log_stream(log_stream),
+ read_debug_names(read_debug_names),
+ stop_on_first_error(stop_on_first_error),
+ fail_on_custom_section_error(fail_on_custom_section_error) {}
+
+ Features features;
+ Stream* log_stream = nullptr;
+ bool read_debug_names = false;
+ bool stop_on_first_error = true;
+ bool fail_on_custom_section_error = true;
+ bool skip_function_bodies = false;
+};
+
+// TODO: Move somewhere else?
+struct TypeMut {
+ Type type;
+ bool mutable_;
+};
+using TypeMutVector = std::vector<TypeMut>;
+
+class BinaryReaderDelegate {
+ public:
+ struct State {
+ State(const uint8_t* data, Offset size)
+ : data(data), size(size), offset(0) {}
+
+ const uint8_t* data;
+ Offset size;
+ Offset offset;
+ };
+
+ virtual ~BinaryReaderDelegate() {}
+
+ virtual bool OnError(const Error&) = 0;
+ virtual void OnSetState(const State* s) { state = s; }
+
+ /* Module */
+ virtual Result BeginModule(uint32_t version) = 0;
+ virtual Result EndModule() = 0;
+
+ virtual Result BeginSection(Index section_index,
+ BinarySection section_type,
+ Offset size) = 0;
+
+ /* Custom section */
+ virtual Result BeginCustomSection(Index section_index,
+ Offset size,
+ std::string_view section_name) = 0;
+ virtual Result EndCustomSection() = 0;
+
+ /* Type section */
+ virtual Result BeginTypeSection(Offset size) = 0;
+ virtual Result OnTypeCount(Index count) = 0;
+ virtual Result OnFuncType(Index index,
+ Index param_count,
+ Type* param_types,
+ Index result_count,
+ Type* result_types) = 0;
+ virtual Result OnStructType(Index index,
+ Index field_count,
+ TypeMut* fields) = 0;
+ virtual Result OnArrayType(Index index, TypeMut field) = 0;
+ virtual Result EndTypeSection() = 0;
+
+ /* Import section */
+ virtual Result BeginImportSection(Offset size) = 0;
+ virtual Result OnImportCount(Index count) = 0;
+ virtual Result OnImport(Index index,
+ ExternalKind kind,
+ std::string_view module_name,
+ std::string_view field_name) = 0;
+ virtual Result OnImportFunc(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index func_index,
+ Index sig_index) = 0;
+ virtual Result OnImportTable(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index table_index,
+ Type elem_type,
+ const Limits* elem_limits) = 0;
+ virtual Result OnImportMemory(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index memory_index,
+ const Limits* page_limits) = 0;
+ virtual Result OnImportGlobal(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index global_index,
+ Type type,
+ bool mutable_) = 0;
+ virtual Result OnImportTag(Index import_index,
+ std::string_view module_name,
+ std::string_view field_name,
+ Index tag_index,
+ Index sig_index) = 0;
+ virtual Result EndImportSection() = 0;
+
+ /* Function section */
+ virtual Result BeginFunctionSection(Offset size) = 0;
+ virtual Result OnFunctionCount(Index count) = 0;
+ virtual Result OnFunction(Index index, Index sig_index) = 0;
+ virtual Result EndFunctionSection() = 0;
+
+ /* Table section */
+ virtual Result BeginTableSection(Offset size) = 0;
+ virtual Result OnTableCount(Index count) = 0;
+ virtual Result OnTable(Index index,
+ Type elem_type,
+ const Limits* elem_limits) = 0;
+ virtual Result EndTableSection() = 0;
+
+ /* Memory section */
+ virtual Result BeginMemorySection(Offset size) = 0;
+ virtual Result OnMemoryCount(Index count) = 0;
+ virtual Result OnMemory(Index index, const Limits* limits) = 0;
+ virtual Result EndMemorySection() = 0;
+
+ /* Global section */
+ virtual Result BeginGlobalSection(Offset size) = 0;
+ virtual Result OnGlobalCount(Index count) = 0;
+ virtual Result BeginGlobal(Index index, Type type, bool mutable_) = 0;
+ virtual Result BeginGlobalInitExpr(Index index) = 0;
+ virtual Result EndGlobalInitExpr(Index index) = 0;
+ virtual Result EndGlobal(Index index) = 0;
+ virtual Result EndGlobalSection() = 0;
+
+ /* Exports section */
+ virtual Result BeginExportSection(Offset size) = 0;
+ virtual Result OnExportCount(Index count) = 0;
+ virtual Result OnExport(Index index,
+ ExternalKind kind,
+ Index item_index,
+ std::string_view name) = 0;
+ virtual Result EndExportSection() = 0;
+
+ /* Start section */
+ virtual Result BeginStartSection(Offset size) = 0;
+ virtual Result OnStartFunction(Index func_index) = 0;
+ virtual Result EndStartSection() = 0;
+
+ /* Code section */
+ virtual Result BeginCodeSection(Offset size) = 0;
+ virtual Result OnFunctionBodyCount(Index count) = 0;
+ virtual Result BeginFunctionBody(Index index, Offset size) = 0;
+ virtual Result OnLocalDeclCount(Index count) = 0;
+ virtual Result OnLocalDecl(Index decl_index, Index count, Type type) = 0;
+
+ /* Function expressions; called between BeginFunctionBody and
+ EndFunctionBody */
+ virtual Result OnOpcode(Opcode Opcode) = 0;
+ virtual Result OnOpcodeBare() = 0;
+ virtual Result OnOpcodeUint32(uint32_t value) = 0;
+ virtual Result OnOpcodeIndex(Index value) = 0;
+ virtual Result OnOpcodeIndexIndex(Index value, Index value2) = 0;
+ virtual Result OnOpcodeUint32Uint32(uint32_t value, uint32_t value2) = 0;
+ virtual Result OnOpcodeUint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3) = 0;
+ virtual Result OnOpcodeUint32Uint32Uint32Uint32(uint32_t value,
+ uint32_t value2,
+ uint32_t value3,
+ uint32_t value4) = 0;
+ virtual Result OnOpcodeUint64(uint64_t value) = 0;
+ virtual Result OnOpcodeF32(uint32_t value) = 0;
+ virtual Result OnOpcodeF64(uint64_t value) = 0;
+ virtual Result OnOpcodeV128(v128 value) = 0;
+ virtual Result OnOpcodeBlockSig(Type sig_type) = 0;
+ virtual Result OnOpcodeType(Type type) = 0;
+ virtual Result OnAtomicLoadExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnAtomicStoreExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnAtomicRmwExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnAtomicWaitExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnAtomicFenceExpr(uint32_t consistency_model) = 0;
+ virtual Result OnAtomicNotifyExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnBinaryExpr(Opcode opcode) = 0;
+ virtual Result OnBlockExpr(Type sig_type) = 0;
+ virtual Result OnBrExpr(Index depth) = 0;
+ virtual Result OnBrIfExpr(Index depth) = 0;
+ virtual Result OnBrTableExpr(Index num_targets,
+ Index* target_depths,
+ Index default_target_depth) = 0;
+ virtual Result OnCallExpr(Index func_index) = 0;
+ virtual Result OnCallIndirectExpr(Index sig_index, Index table_index) = 0;
+ virtual Result OnCallRefExpr() = 0;
+ virtual Result OnCatchExpr(Index tag_index) = 0;
+ virtual Result OnCatchAllExpr() = 0;
+ virtual Result OnCompareExpr(Opcode opcode) = 0;
+ virtual Result OnConvertExpr(Opcode opcode) = 0;
+ virtual Result OnDelegateExpr(Index depth) = 0;
+ virtual Result OnDropExpr() = 0;
+ virtual Result OnElseExpr() = 0;
+ virtual Result OnEndExpr() = 0;
+ virtual Result OnF32ConstExpr(uint32_t value_bits) = 0;
+ virtual Result OnF64ConstExpr(uint64_t value_bits) = 0;
+ virtual Result OnV128ConstExpr(v128 value_bits) = 0;
+ virtual Result OnGlobalGetExpr(Index global_index) = 0;
+ virtual Result OnGlobalSetExpr(Index global_index) = 0;
+ virtual Result OnI32ConstExpr(uint32_t value) = 0;
+ virtual Result OnI64ConstExpr(uint64_t value) = 0;
+ virtual Result OnIfExpr(Type sig_type) = 0;
+ virtual Result OnLoadExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnLocalGetExpr(Index local_index) = 0;
+ virtual Result OnLocalSetExpr(Index local_index) = 0;
+ virtual Result OnLocalTeeExpr(Index local_index) = 0;
+ virtual Result OnLoopExpr(Type sig_type) = 0;
+ virtual Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) = 0;
+ virtual Result OnDataDropExpr(Index segment_index) = 0;
+ virtual Result OnMemoryFillExpr(Index memidx) = 0;
+ virtual Result OnMemoryGrowExpr(Index memidx) = 0;
+ virtual Result OnMemoryInitExpr(Index segment_index, Index memidx) = 0;
+ virtual Result OnMemorySizeExpr(Index memidx) = 0;
+ virtual Result OnTableCopyExpr(Index dst_index, Index src_index) = 0;
+ virtual Result OnElemDropExpr(Index segment_index) = 0;
+ virtual Result OnTableInitExpr(Index segment_index, Index table_index) = 0;
+ virtual Result OnTableGetExpr(Index table_index) = 0;
+ virtual Result OnTableSetExpr(Index table_index) = 0;
+ virtual Result OnTableGrowExpr(Index table_index) = 0;
+ virtual Result OnTableSizeExpr(Index table_index) = 0;
+ virtual Result OnTableFillExpr(Index table_index) = 0;
+ virtual Result OnRefFuncExpr(Index func_index) = 0;
+ virtual Result OnRefNullExpr(Type type) = 0;
+ virtual Result OnRefIsNullExpr() = 0;
+ virtual Result OnNopExpr() = 0;
+ virtual Result OnRethrowExpr(Index depth) = 0;
+ virtual Result OnReturnExpr() = 0;
+ virtual Result OnReturnCallExpr(Index func_index) = 0;
+ virtual Result OnReturnCallIndirectExpr(Index sig_index,
+ Index table_index) = 0;
+ virtual Result OnSelectExpr(Index result_count, Type* result_types) = 0;
+ virtual Result OnStoreExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnThrowExpr(Index tag_index) = 0;
+ virtual Result OnTryExpr(Type sig_type) = 0;
+
+ virtual Result OnUnaryExpr(Opcode opcode) = 0;
+ virtual Result OnTernaryExpr(Opcode opcode) = 0;
+ virtual Result OnUnreachableExpr() = 0;
+ virtual Result EndFunctionBody(Index index) = 0;
+ virtual Result EndCodeSection() = 0;
+
+ /* Simd instructions with Lane Imm operand*/
+ virtual Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) = 0;
+ virtual Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) = 0;
+ virtual Result OnSimdLoadLaneExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset,
+ uint64_t value) = 0;
+ virtual Result OnSimdStoreLaneExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset,
+ uint64_t value) = 0;
+
+ virtual Result OnLoadSplatExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+ virtual Result OnLoadZeroExpr(Opcode opcode,
+ Index memidx,
+ Address alignment_log2,
+ Address offset) = 0;
+
+ /* Elem section */
+ virtual Result BeginElemSection(Offset size) = 0;
+ virtual Result OnElemSegmentCount(Index count) = 0;
+ virtual Result BeginElemSegment(Index index,
+ Index table_index,
+ uint8_t flags) = 0;
+ virtual Result BeginElemSegmentInitExpr(Index index) = 0;
+ virtual Result EndElemSegmentInitExpr(Index index) = 0;
+ virtual Result OnElemSegmentElemType(Index index, Type elem_type) = 0;
+ virtual Result OnElemSegmentElemExprCount(Index index, Index count) = 0;
+ virtual Result OnElemSegmentElemExpr_RefNull(Index segment_index,
+ Type type) = 0;
+ virtual Result OnElemSegmentElemExpr_RefFunc(Index segment_index,
+ Index func_index) = 0;
+ virtual Result EndElemSegment(Index index) = 0;
+ virtual Result EndElemSection() = 0;
+
+ /* Data section */
+ virtual Result BeginDataSection(Offset size) = 0;
+ virtual Result OnDataSegmentCount(Index count) = 0;
+ virtual Result BeginDataSegment(Index index,
+ Index memory_index,
+ uint8_t flags) = 0;
+ virtual Result BeginDataSegmentInitExpr(Index index) = 0;
+ virtual Result EndDataSegmentInitExpr(Index index) = 0;
+ virtual Result OnDataSegmentData(Index index,
+ const void* data,
+ Address size) = 0;
+ virtual Result EndDataSegment(Index index) = 0;
+ virtual Result EndDataSection() = 0;
+
+ /* DataCount section */
+ virtual Result BeginDataCountSection(Offset size) = 0;
+ virtual Result OnDataCount(Index count) = 0;
+ virtual Result EndDataCountSection() = 0;
+
+ /* Names section */
+ virtual Result BeginNamesSection(Offset size) = 0;
+ virtual Result OnModuleNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) = 0;
+ virtual Result OnModuleName(std::string_view name) = 0;
+ virtual Result OnFunctionNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) = 0;
+ virtual Result OnFunctionNamesCount(Index num_functions) = 0;
+ virtual Result OnFunctionName(Index function_index,
+ std::string_view function_name) = 0;
+ virtual Result OnLocalNameSubsection(Index index,
+ uint32_t name_type,
+ Offset subsection_size) = 0;
+ virtual Result OnLocalNameFunctionCount(Index num_functions) = 0;
+ virtual Result OnLocalNameLocalCount(Index function_index,
+ Index num_locals) = 0;
+ virtual Result OnLocalName(Index function_index,
+ Index local_index,
+ std::string_view local_name) = 0;
+ virtual Result OnNameSubsection(Index index,
+ NameSectionSubsection subsection_type,
+ Offset subsection_size) = 0;
+ virtual Result OnNameCount(Index num_names) = 0;
+ virtual Result OnNameEntry(NameSectionSubsection type,
+ Index index,
+ std::string_view name) = 0;
+ virtual Result EndNamesSection() = 0;
+
+ /* Reloc section */
+ virtual Result BeginRelocSection(Offset size) = 0;
+ virtual Result OnRelocCount(Index count, Index section_index) = 0;
+ virtual Result OnReloc(RelocType type,
+ Offset offset,
+ Index index,
+ uint32_t addend) = 0;
+ virtual Result EndRelocSection() = 0;
+
+ /* Dylink section */
+ virtual Result BeginDylinkSection(Offset size) = 0;
+ virtual Result OnDylinkInfo(uint32_t mem_size,
+ uint32_t mem_align_log2,
+ uint32_t table_size,
+ uint32_t table_align_log2) = 0;
+ virtual Result OnDylinkImportCount(Index count) = 0;
+ virtual Result OnDylinkExportCount(Index count) = 0;
+ virtual Result OnDylinkImport(std::string_view module,
+ std::string_view name,
+ uint32_t flags) = 0;
+ virtual Result OnDylinkExport(std::string_view name, uint32_t flags) = 0;
+ virtual Result OnDylinkNeededCount(Index count) = 0;
+ virtual Result OnDylinkNeeded(std::string_view so_name) = 0;
+ virtual Result EndDylinkSection() = 0;
+
+ /* target_features section */
+ virtual Result BeginTargetFeaturesSection(Offset size) = 0;
+ virtual Result OnFeatureCount(Index count) = 0;
+ virtual Result OnFeature(uint8_t prefix, std::string_view name) = 0;
+ virtual Result EndTargetFeaturesSection() = 0;
+
+ /* Linking section */
+ virtual Result BeginLinkingSection(Offset size) = 0;
+ virtual Result OnSymbolCount(Index count) = 0;
+ virtual Result OnDataSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index segment,
+ uint32_t offset,
+ uint32_t size) = 0;
+ virtual Result OnFunctionSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index function_index) = 0;
+ virtual Result OnGlobalSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index global_index) = 0;
+ virtual Result OnSectionSymbol(Index index,
+ uint32_t flags,
+ Index section_index) = 0;
+ virtual Result OnTagSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index tag_index) = 0;
+ virtual Result OnTableSymbol(Index index,
+ uint32_t flags,
+ std::string_view name,
+ Index table_index) = 0;
+ virtual Result OnSegmentInfoCount(Index count) = 0;
+ virtual Result OnSegmentInfo(Index index,
+ std::string_view name,
+ Address alignment_log2,
+ uint32_t flags) = 0;
+ virtual Result OnInitFunctionCount(Index count) = 0;
+ virtual Result OnInitFunction(uint32_t priority, Index symbol_index) = 0;
+ virtual Result OnComdatCount(Index count) = 0;
+ virtual Result OnComdatBegin(std::string_view name,
+ uint32_t flags,
+ Index count) = 0;
+ virtual Result OnComdatEntry(ComdatType kind, Index index) = 0;
+ virtual Result EndLinkingSection() = 0;
+
+ /* Tag section */
+ virtual Result BeginTagSection(Offset size) = 0;
+ virtual Result OnTagCount(Index count) = 0;
+ virtual Result OnTagType(Index index, Index sig_index) = 0;
+ virtual Result EndTagSection() = 0;
+
+ /* Code Metadata sections */
+ virtual Result BeginCodeMetadataSection(std::string_view name,
+ Offset size) = 0;
+ virtual Result OnCodeMetadataFuncCount(Index count) = 0;
+ virtual Result OnCodeMetadataCount(Index function_index, Index count) = 0;
+ virtual Result OnCodeMetadata(Offset offset,
+ const void* data,
+ Address size) = 0;
+ virtual Result EndCodeMetadataSection() = 0;
+
+ const State* state = nullptr;
+};
+
+Result ReadBinary(const void* data,
+ size_t size,
+ BinaryReaderDelegate* reader,
+ const ReadBinaryOptions& options);
+
+size_t ReadU32Leb128(const uint8_t* ptr,
+ const uint8_t* end,
+ uint32_t* out_value);
+
+size_t ReadI32Leb128(const uint8_t* ptr,
+ const uint8_t* end,
+ uint32_t* out_value);
+
+} // namespace wabt
+
+#endif /* WABT_BINARY_READER_H_ */
diff --git a/third_party/wasm2c/include/wabt/binary-writer-spec.h b/third_party/wasm2c/include/wabt/binary-writer-spec.h
new file mode 100644
index 0000000000..168c65efdf
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary-writer-spec.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINARY_WRITER_SPEC_H_
+#define WABT_BINARY_WRITER_SPEC_H_
+
+#include <functional>
+#include <utility>
+#include <vector>
+
+#include "wabt/binary-writer.h"
+#include "wabt/common.h"
+#include "wabt/ir.h"
+
+namespace wabt {
+
+struct FilenameMemoryStreamPair {
+ FilenameMemoryStreamPair(std::string_view filename,
+ std::unique_ptr<MemoryStream> stream)
+ : filename(filename), stream(std::move(stream)) {}
+ std::string filename;
+ std::unique_ptr<MemoryStream> stream;
+};
+
+using WriteBinarySpecStreamFactory =
+ std::function<Stream*(std::string_view filename)>;
+
+Result WriteBinarySpecScript(Stream* json_stream,
+ WriteBinarySpecStreamFactory module_stream_factory,
+ Script*,
+ std::string_view source_filename,
+ std::string_view module_filename_noext,
+ const WriteBinaryOptions&);
+
+// Convenience function for producing MemoryStream outputs all modules.
+Result WriteBinarySpecScript(
+ Stream* json_stream,
+ Script*,
+ std::string_view source_filename,
+ std::string_view module_filename_noext,
+ const WriteBinaryOptions&,
+ std::vector<FilenameMemoryStreamPair>* out_module_streams,
+ Stream* log_stream = nullptr);
+
+} // namespace wabt
+
+#endif /* WABT_BINARY_WRITER_SPEC_H_ */
diff --git a/third_party/wasm2c/include/wabt/binary-writer.h b/third_party/wasm2c/include/wabt/binary-writer.h
new file mode 100644
index 0000000000..dedba1bdcf
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary-writer.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINARY_WRITER_H_
+#define WABT_BINARY_WRITER_H_
+
+#include "wabt/common.h"
+#include "wabt/feature.h"
+#include "wabt/opcode.h"
+#include "wabt/stream.h"
+
+namespace wabt {
+
+struct Module;
+struct Script;
+
+struct WriteBinaryOptions {
+ WriteBinaryOptions() = default;
+ WriteBinaryOptions(const Features& features,
+ bool canonicalize_lebs,
+ bool relocatable,
+ bool write_debug_names)
+ : features(features),
+ canonicalize_lebs(canonicalize_lebs),
+ relocatable(relocatable),
+ write_debug_names(write_debug_names) {}
+
+ Features features;
+ bool canonicalize_lebs = true;
+ bool relocatable = false;
+ bool write_debug_names = false;
+};
+
+Result WriteBinaryModule(Stream*, const Module*, const WriteBinaryOptions&);
+
+void WriteType(Stream* stream, Type type, const char* desc = nullptr);
+
+void WriteStr(Stream* stream,
+ std::string_view s,
+ const char* desc,
+ PrintChars print_chars = PrintChars::No);
+
+void WriteOpcode(Stream* stream, Opcode opcode);
+
+void WriteLimits(Stream* stream, const Limits* limits);
+
+} // namespace wabt
+
+#endif /* WABT_BINARY_WRITER_H_ */
diff --git a/third_party/wasm2c/include/wabt/binary.h b/third_party/wasm2c/include/wabt/binary.h
new file mode 100644
index 0000000000..485f15cbd3
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binary.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINARY_H_
+#define WABT_BINARY_H_
+
+#include "wabt/common.h"
+
+#define WABT_BINARY_MAGIC 0x6d736100
+#define WABT_BINARY_VERSION 1
+#define WABT_BINARY_LIMITS_HAS_MAX_FLAG 0x1
+#define WABT_BINARY_LIMITS_IS_SHARED_FLAG 0x2
+#define WABT_BINARY_LIMITS_IS_64_FLAG 0x4
+#define WABT_BINARY_LIMITS_ALL_FLAGS \
+ (WABT_BINARY_LIMITS_HAS_MAX_FLAG | WABT_BINARY_LIMITS_IS_SHARED_FLAG | \
+ WABT_BINARY_LIMITS_IS_64_FLAG)
+
+#define WABT_BINARY_SECTION_NAME "name"
+#define WABT_BINARY_SECTION_RELOC "reloc"
+#define WABT_BINARY_SECTION_LINKING "linking"
+#define WABT_BINARY_SECTION_TARGET_FEATURES "target_features"
+#define WABT_BINARY_SECTION_DYLINK "dylink"
+#define WABT_BINARY_SECTION_DYLINK0 "dylink.0"
+#define WABT_BINARY_SECTION_CODE_METADATA "metadata.code."
+
+#define WABT_FOREACH_BINARY_SECTION(V) \
+ V(Custom, custom, 0) \
+ V(Type, type, 1) \
+ V(Import, import, 2) \
+ V(Function, function, 3) \
+ V(Table, table, 4) \
+ V(Memory, memory, 5) \
+ V(Tag, tag, 13) \
+ V(Global, global, 6) \
+ V(Export, export, 7) \
+ V(Start, start, 8) \
+ V(Elem, elem, 9) \
+ V(DataCount, data_count, 12) \
+ V(Code, code, 10) \
+ V(Data, data, 11)
+
+namespace wabt {
+
+/* clang-format off */
+enum class BinarySection {
+#define V(Name, name, code) Name = code,
+ WABT_FOREACH_BINARY_SECTION(V)
+#undef V
+ Invalid = ~0,
+
+ First = Custom,
+ Last = Tag,
+};
+/* clang-format on */
+constexpr int kBinarySectionCount = WABT_ENUM_COUNT(BinarySection);
+
+enum class BinarySectionOrder {
+#define V(Name, name, code) Name,
+ WABT_FOREACH_BINARY_SECTION(V)
+#undef V
+};
+
+BinarySectionOrder GetSectionOrder(BinarySection);
+const char* GetSectionName(BinarySection);
+
+// See
+// https://github.com/WebAssembly/extended-name-section/blob/main/proposals/extended-name-section/Overview.md
+enum class NameSectionSubsection {
+ Module = 0,
+ Function = 1,
+ Local = 2,
+ Label = 3,
+ Type = 4,
+ Table = 5,
+ Memory = 6,
+ Global = 7,
+ ElemSegment = 8,
+ DataSegment = 9,
+ // tag names are yet part of the extended-name-section proposal (because it
+ // only deals with naming things that are in the spec already). However, we
+ // include names for Tags in wabt using this enum value on the basis that tags
+ // can only exist when exceptions are enabled and that engines should ignore
+ // unknown name types.
+ Tag = 10,
+
+ First = Module,
+ Last = Tag,
+};
+const char* GetNameSectionSubsectionName(NameSectionSubsection subsec);
+
+} // namespace wabt
+
+#endif /* WABT_BINARY_H_ */
diff --git a/third_party/wasm2c/include/wabt/binding-hash.h b/third_party/wasm2c/include/wabt/binding-hash.h
new file mode 100644
index 0000000000..5d43cd7202
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/binding-hash.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_BINDING_HASH_H_
+#define WABT_BINDING_HASH_H_
+
+#include <functional>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+struct Var;
+
+struct Binding {
+ explicit Binding(Index index) : index(index) {}
+ Binding(const Location& loc, Index index) : loc(loc), index(index) {}
+
+ Location loc;
+ Index index;
+};
+
+// This class derives from a C++ container, which is usually not advisable
+// because they don't have virtual destructors. So don't delete a BindingHash
+// object through a pointer to std::unordered_multimap.
+class BindingHash : public std::unordered_multimap<std::string, Binding> {
+ public:
+ using DuplicateCallback =
+ std::function<void(const value_type&, const value_type&)>;
+
+ void FindDuplicates(DuplicateCallback callback) const;
+
+ Index FindIndex(const Var&) const;
+
+ Index FindIndex(const std::string& name) const {
+ auto iter = find(name);
+ return iter != end() ? iter->second.index : kInvalidIndex;
+ }
+
+ Index FindIndex(std::string_view name) const {
+ return FindIndex(std::string(name));
+ }
+
+ private:
+ using ValueTypeVector = std::vector<const value_type*>;
+
+ void CreateDuplicatesVector(ValueTypeVector* out_duplicates) const;
+ void SortDuplicatesVectorByLocation(ValueTypeVector* duplicates) const;
+ void CallCallbacks(const ValueTypeVector& duplicates,
+ DuplicateCallback callback) const;
+};
+
+} // namespace wabt
+
+#endif /* WABT_BINDING_HASH_H_ */
diff --git a/third_party/wasm2c/include/wabt/c-writer.h b/third_party/wasm2c/include/wabt/c-writer.h
new file mode 100644
index 0000000000..7d9ff6ad74
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/c-writer.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_C_WRITER_H_
+#define WABT_C_WRITER_H_
+
+#include <functional>
+#include "wabt/common.h"
+#include "wabt/feature.h"
+#include "wabt/ir.h"
+
+namespace wabt {
+
+struct Module;
+class Stream;
+
+struct WriteCOptions {
+ std::string_view module_name;
+ /* Set of wasm features enabled for wasm2c */
+ Features* features;
+ /*
+ * name_to_output_file_index takes const iterators to begin and end of a list
+ * of all functions in the module, number of imported functions, and number of
+ * .c outputs as argument, returns a vector where vector[i] the index of the
+ * .c output that funcs_begin + i goes into. Only called when --num-outputs is
+ * used.
+ */
+ std::function<std::vector<size_t>(
+ std::vector<Func*>::const_iterator funcs_begin,
+ std::vector<Func*>::const_iterator funcs_end,
+ size_t num_imported_functions,
+ size_t num_outputs)>
+ name_to_output_file_index;
+};
+
+Result WriteC(std::vector<Stream*>&& c_streams,
+ Stream* h_stream,
+ Stream* h_impl_stream,
+ const char* header_name,
+ const char* header_impl_name,
+ const Module*,
+ const WriteCOptions&);
+
+} // namespace wabt
+
+#endif /* WABT_C_WRITER_H_ */
diff --git a/third_party/wasm2c/include/wabt/cast.h b/third_party/wasm2c/include/wabt/cast.h
new file mode 100644
index 0000000000..f089e2f18e
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/cast.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_CAST_H_
+#define WABT_CAST_H_
+
+#include <memory>
+#include <type_traits>
+
+#include "wabt/common.h"
+
+// Modeled after LLVM's dynamic casts:
+// http://llvm.org/docs/ProgrammersManual.html#the-isa-cast-and-dyn-cast-templates
+//
+// Use isa<T>(foo) to check whether foo is a T*:
+//
+// if (isa<Minivan>(car)) {
+// ...
+// }
+//
+// Use cast<T>(foo) when you know that foo is a T* -- it will assert that the
+// type matches:
+//
+// switch (car.type) {
+// case CarType::Minivan: {
+// auto minivan = cast<Minivan>(car);
+// ...
+// }
+// }
+//
+// Use dyn_cast<T>(foo) as a combination if isa and cast, it will return
+// nullptr if the type doesn't match:
+//
+// if (auto minivan = dyn_cast<Minivan>(car)) {
+// ...
+// }
+//
+//
+// To use these classes in a type hierarchy, you must implement classof:
+//
+// enum CarType { Minivan, ... };
+// struct Car { CarType type; ... };
+// struct Minivan : Car {
+// static bool classof(const Car* car) { return car->type == Minivan; }
+// ...
+// };
+//
+
+namespace wabt {
+
+template <typename Derived, typename Base>
+bool isa(const Base* base) {
+ WABT_STATIC_ASSERT((std::is_base_of<Base, Derived>::value));
+ return Derived::classof(base);
+}
+
+template <typename Derived, typename Base>
+const Derived* cast(const Base* base) {
+ assert(isa<Derived>(base));
+ return static_cast<const Derived*>(base);
+};
+
+template <typename Derived, typename Base>
+Derived* cast(Base* base) {
+ assert(isa<Derived>(base));
+ return static_cast<Derived*>(base);
+};
+
+template <typename Derived, typename Base>
+const Derived* dyn_cast(const Base* base) {
+ return isa<Derived>(base) ? static_cast<const Derived*>(base) : nullptr;
+};
+
+template <typename Derived, typename Base>
+Derived* dyn_cast(Base* base) {
+ return isa<Derived>(base) ? static_cast<Derived*>(base) : nullptr;
+};
+
+// Cast functionality for unique_ptr. isa and dyn_cast are not included because
+// they won't always pass ownership back to the caller.
+
+template <typename Derived, typename Base>
+std::unique_ptr<const Derived> cast(std::unique_ptr<const Base>&& base) {
+ assert(isa<Derived>(base.get()));
+ return std::unique_ptr<Derived>(static_cast<const Derived*>(base.release()));
+};
+
+template <typename Derived, typename Base>
+std::unique_ptr<Derived> cast(std::unique_ptr<Base>&& base) {
+ assert(isa<Derived>(base.get()));
+ return std::unique_ptr<Derived>(static_cast<Derived*>(base.release()));
+};
+
+} // namespace wabt
+
+#endif // WABT_CAST_H_
diff --git a/third_party/wasm2c/include/wabt/circular-array.h b/third_party/wasm2c/include/wabt/circular-array.h
new file mode 100644
index 0000000000..9e2d38004b
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/circular-array.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_CIRCULAR_ARRAY_H_
+#define WABT_CIRCULAR_ARRAY_H_
+
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <type_traits>
+
+namespace wabt {
+
+// TODO(karlschimpf) Complete the API
+// Note: Capacity must be a power of 2.
+template <class T, size_t kCapacity>
+class CircularArray {
+ public:
+ using value_type = T;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ CircularArray() {
+ static_assert(kCapacity && ((kCapacity & (kCapacity - 1)) == 0),
+ "Capacity must be a power of 2.");
+ }
+
+ CircularArray(const CircularArray&) = default;
+ CircularArray& operator=(const CircularArray&) = default;
+
+ CircularArray(CircularArray&&) = default;
+ CircularArray& operator=(CircularArray&&) = default;
+
+ ~CircularArray() { clear(); }
+
+ reference at(size_type index) {
+ assert(index < size_);
+ return (*this)[index];
+ }
+
+ const_reference at(size_type index) const {
+ assert(index < size_);
+ return (*this)[index];
+ }
+
+ reference operator[](size_type index) { return contents_[position(index)]; }
+
+ const_reference operator[](size_type index) const {
+ return contents_[position(index)];
+ }
+
+ reference back() { return at(size_ - 1); }
+
+ const_reference back() const { return at(size_ - 1); }
+
+ bool empty() const { return size_ == 0; }
+
+ reference front() { return at(0); }
+
+ const_reference front() const { return at(0); }
+
+ size_type max_size() const { return kCapacity; }
+
+ void pop_back() {
+ assert(size_ > 0);
+ SetElement(back());
+ --size_;
+ }
+
+ void pop_front() {
+ assert(size_ > 0);
+ SetElement(front());
+ front_ = (front_ + 1) & kMask;
+ --size_;
+ }
+
+ void push_back(const value_type& value) {
+ assert(size_ < kCapacity);
+ SetElement(at(size_++), value);
+ }
+
+ size_type size() const { return size_; }
+
+ void clear() {
+ while (!empty()) {
+ pop_back();
+ }
+ }
+
+ private:
+ static constexpr size_type kMask = kCapacity - 1;
+
+ size_t position(size_t index) const { return (front_ + index) & kMask; }
+
+ template <typename... Args>
+ void SetElement(reference element, Args&&... args) {
+ element.~T();
+ new (&element) T(std::forward<Args>(args)...);
+ }
+
+ std::array<T, kCapacity> contents_;
+ size_type size_ = 0;
+ size_type front_ = 0;
+};
+
+} // namespace wabt
+
+#endif // WABT_CIRCULAR_ARRAY_H_
diff --git a/third_party/wasm2c/include/wabt/color.h b/third_party/wasm2c/include/wabt/color.h
new file mode 100644
index 0000000000..8af57f33f7
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/color.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_COLOR_H_
+#define WABT_COLOR_H_
+
+#include <cstdio>
+
+namespace wabt {
+
+#define WABT_FOREACH_COLOR_CODE(V) \
+ V(Default, "\x1b[0m") \
+ V(Bold, "\x1b[1m") \
+ V(NoBold, "\x1b[22m") \
+ V(Black, "\x1b[30m") \
+ V(Red, "\x1b[31m") \
+ V(Green, "\x1b[32m") \
+ V(Yellow, "\x1b[33m") \
+ V(Blue, "\x1b[34m") \
+ V(Magenta, "\x1b[35m") \
+ V(Cyan, "\x1b[36m") \
+ V(White, "\x1b[37m")
+
+class Color {
+ public:
+ Color() : file_(nullptr), enabled_(false) {}
+ Color(FILE*, bool enabled = true);
+
+// Write the given color to the file, if enabled.
+#define WABT_COLOR(Name, code) \
+ void Name() const { WriteCode(Name##Code()); }
+ WABT_FOREACH_COLOR_CODE(WABT_COLOR)
+#undef WABT_COLOR
+
+// Get the color code as a string, if enabled.
+#define WABT_COLOR(Name, code) \
+ const char* Maybe##Name##Code() const { return enabled_ ? Name##Code() : ""; }
+ WABT_FOREACH_COLOR_CODE(WABT_COLOR)
+#undef WABT_COLOR
+
+// Get the color code as a string.
+#define WABT_COLOR(Name, code) \
+ static const char* Name##Code() { return code; }
+ WABT_FOREACH_COLOR_CODE(WABT_COLOR)
+#undef WABT_COLOR
+
+ private:
+ static bool SupportsColor(FILE*);
+ void WriteCode(const char*) const;
+
+ FILE* file_;
+ bool enabled_;
+};
+
+#undef WABT_FOREACH_COLOR_CODE
+
+} // namespace wabt
+
+#endif // WABT_COLOR_H_
diff --git a/third_party/wasm2c/include/wabt/common.h b/third_party/wasm2c/include/wabt/common.h
new file mode 100644
index 0000000000..2ae1fa1fe9
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/common.h
@@ -0,0 +1,456 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_COMMON_H_
+#define WABT_COMMON_H_
+
+#include <algorithm>
+#include <cassert>
+#include <cstdarg>
+#include <cstddef>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <vector>
+
+#include "wabt/config.h"
+
+#include "wabt/base-types.h"
+#include "wabt/result.h"
+#include "wabt/string-format.h"
+#include "wabt/type.h"
+
+#define WABT_FATAL(...) fprintf(stderr, __VA_ARGS__), exit(1)
+#define WABT_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#define WABT_USE(x) static_cast<void>(x)
+
+// 64k
+#define WABT_PAGE_SIZE 0x10000
+// # of pages that fit in 32-bit address space
+#define WABT_MAX_PAGES32 0x10000
+// # of pages that fit in 64-bit address space
+#define WABT_MAX_PAGES64 0x1000000000000
+#define WABT_BYTES_TO_PAGES(x) ((x) >> 16)
+#define WABT_ALIGN_UP_TO_PAGE(x) \
+ (((x) + WABT_PAGE_SIZE - 1) & ~(WABT_PAGE_SIZE - 1))
+
+#define WABT_ENUM_COUNT(name) \
+ (static_cast<int>(name::Last) - static_cast<int>(name::First) + 1)
+
+#define WABT_DISALLOW_COPY_AND_ASSIGN(type) \
+ type(const type&) = delete; \
+ type& operator=(const type&) = delete;
+
+#if WITH_EXCEPTIONS
+#define WABT_TRY try {
+#define WABT_CATCH_BAD_ALLOC \
+ } \
+ catch (std::bad_alloc&) { \
+ }
+#define WABT_CATCH_BAD_ALLOC_AND_EXIT \
+ } \
+ catch (std::bad_alloc&) { \
+ WABT_FATAL("Memory allocation failure.\n"); \
+ }
+#else
+#define WABT_TRY
+#define WABT_CATCH_BAD_ALLOC
+#define WABT_CATCH_BAD_ALLOC_AND_EXIT
+#endif
+
+#define PRIindex "u"
+#define PRIaddress PRIu64
+#define PRIoffset PRIzx
+
+namespace wabt {
+inline void MemcpyEndianAware(void* dst,
+ const void* src,
+ size_t dsize,
+ size_t ssize,
+ size_t doff,
+ size_t soff,
+ size_t len) {
+#if WABT_BIG_ENDIAN
+ memcpy(static_cast<char*>(dst) + (dsize) - (len) - (doff),
+ static_cast<const char*>(src) + (ssize) - (len) - (soff), (len));
+#else
+ memcpy(static_cast<char*>(dst) + (doff),
+ static_cast<const char*>(src) + (soff), (len));
+#endif
+}
+}
+
+struct v128 {
+ v128() = default;
+ v128(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) {
+ set_u32(0, x0);
+ set_u32(1, x1);
+ set_u32(2, x2);
+ set_u32(3, x3);
+ }
+
+ bool operator==(const v128& other) const {
+ return std::equal(std::begin(v), std::end(v), std::begin(other.v));
+ }
+ bool operator!=(const v128& other) const { return !(*this == other); }
+
+ uint8_t u8(int lane) const { return To<uint8_t>(lane); }
+ uint16_t u16(int lane) const { return To<uint16_t>(lane); }
+ uint32_t u32(int lane) const { return To<uint32_t>(lane); }
+ uint64_t u64(int lane) const { return To<uint64_t>(lane); }
+ uint32_t f32_bits(int lane) const { return To<uint32_t>(lane); }
+ uint64_t f64_bits(int lane) const { return To<uint64_t>(lane); }
+
+ void set_u8(int lane, uint8_t x) { return From<uint8_t>(lane, x); }
+ void set_u16(int lane, uint16_t x) { return From<uint16_t>(lane, x); }
+ void set_u32(int lane, uint32_t x) { return From<uint32_t>(lane, x); }
+ void set_u64(int lane, uint64_t x) { return From<uint64_t>(lane, x); }
+ void set_f32_bits(int lane, uint32_t x) { return From<uint32_t>(lane, x); }
+ void set_f64_bits(int lane, uint64_t x) { return From<uint64_t>(lane, x); }
+
+ bool is_zero() const {
+ return std::all_of(std::begin(v), std::end(v),
+ [](uint8_t x) { return x == 0; });
+ }
+ void set_zero() { std::fill(std::begin(v), std::end(v), 0); }
+
+ template <typename T>
+ T To(int lane) const {
+ static_assert(sizeof(T) <= sizeof(v), "Invalid cast!");
+ assert((lane + 1) * sizeof(T) <= sizeof(v));
+ T result;
+ wabt::MemcpyEndianAware(&result, v, sizeof(result), sizeof(v), 0,
+ lane * sizeof(T), sizeof(result));
+ return result;
+ }
+
+ template <typename T>
+ void From(int lane, T data) {
+ static_assert(sizeof(T) <= sizeof(v), "Invalid cast!");
+ assert((lane + 1) * sizeof(T) <= sizeof(v));
+ wabt::MemcpyEndianAware(v, &data, sizeof(v), sizeof(data), lane * sizeof(T),
+ 0, sizeof(data));
+ }
+
+ uint8_t v[16];
+};
+
+namespace wabt {
+
+template <typename Dst, typename Src>
+Dst WABT_VECTORCALL Bitcast(Src&& value) {
+ static_assert(sizeof(Src) == sizeof(Dst), "Bitcast sizes must match.");
+ Dst result;
+ memcpy(&result, &value, sizeof(result));
+ return result;
+}
+
+template <typename T>
+void ZeroMemory(T& v) {
+ WABT_STATIC_ASSERT(std::is_pod<T>::value);
+ memset(&v, 0, sizeof(v));
+}
+
+// Placement construct
+template <typename T, typename... Args>
+void Construct(T& placement, Args&&... args) {
+ new (&placement) T(std::forward<Args>(args)...);
+}
+
+// Placement destruct
+template <typename T>
+void Destruct(T& placement) {
+ placement.~T();
+}
+
+enum class LabelType {
+ Func,
+ InitExpr,
+ Block,
+ Loop,
+ If,
+ Else,
+ Try,
+ Catch,
+
+ First = Func,
+ Last = Catch,
+};
+constexpr int kLabelTypeCount = WABT_ENUM_COUNT(LabelType);
+
+struct Location {
+ enum class Type {
+ Text,
+ Binary,
+ };
+
+ Location() : line(0), first_column(0), last_column(0) {}
+ Location(std::string_view filename,
+ int line,
+ int first_column,
+ int last_column)
+ : filename(filename),
+ line(line),
+ first_column(first_column),
+ last_column(last_column) {}
+ explicit Location(size_t offset) : offset(offset) {}
+
+ std::string_view filename;
+ union {
+ // For text files.
+ struct {
+ int line;
+ int first_column;
+ int last_column;
+ };
+ // For binary files.
+ struct {
+ size_t offset;
+ };
+ };
+};
+
+enum class SegmentKind {
+ Active,
+ Passive,
+ Declared,
+};
+
+// Used in test asserts for special expected values "nan:canonical" and
+// "nan:arithmetic"
+enum class ExpectedNan {
+ None,
+ Canonical,
+ Arithmetic,
+};
+
+// Matches binary format, do not change.
+enum SegmentFlags : uint8_t {
+ SegFlagsNone = 0,
+ SegPassive = 1, // bit 0: Is passive
+ SegExplicitIndex = 2, // bit 1: Has explict index (Implies table 0 if absent)
+ SegDeclared = 3, // Only used for declared segments
+ SegUseElemExprs = 4, // bit 2: Is elemexpr (Or else index sequence)
+
+ SegFlagMax = (SegUseElemExprs << 1) - 1, // All bits set.
+};
+
+enum class RelocType {
+ FuncIndexLEB = 0, // e.g. Immediate of call instruction
+ TableIndexSLEB = 1, // e.g. Loading address of function
+ TableIndexI32 = 2, // e.g. Function address in DATA
+ MemoryAddressLEB = 3, // e.g. Memory address in load/store offset immediate
+ MemoryAddressSLEB = 4, // e.g. Memory address in i32.const
+ MemoryAddressI32 = 5, // e.g. Memory address in DATA
+ TypeIndexLEB = 6, // e.g. Immediate type in call_indirect
+ GlobalIndexLEB = 7, // e.g. Immediate of global.get inst
+ FunctionOffsetI32 = 8, // e.g. Code offset in DWARF metadata
+ SectionOffsetI32 = 9, // e.g. Section offset in DWARF metadata
+ TagIndexLEB = 10, // Used in throw instructions
+ MemoryAddressRelSLEB = 11, // In PIC code, addr relative to __memory_base
+ TableIndexRelSLEB = 12, // In PIC code, table index relative to __table_base
+ GlobalIndexI32 = 13, // e.g. Global index in data (e.g. DWARF)
+ MemoryAddressLEB64 = 14, // Memory64: Like MemoryAddressLEB
+ MemoryAddressSLEB64 = 15, // Memory64: Like MemoryAddressSLEB
+ MemoryAddressI64 = 16, // Memory64: Like MemoryAddressI32
+ MemoryAddressRelSLEB64 = 17, // Memory64: Like MemoryAddressRelSLEB
+ TableIndexSLEB64 = 18, // Memory64: Like TableIndexSLEB
+ TableIndexI64 = 19, // Memory64: Like TableIndexI32
+ TableNumberLEB = 20, // e.g. Immediate of table.get
+ MemoryAddressTLSSLEB = 21, // Address relative to __tls_base
+ MemoryAddressTLSI32 = 22, // Address relative to __tls_base
+
+ First = FuncIndexLEB,
+ Last = MemoryAddressTLSI32,
+};
+constexpr int kRelocTypeCount = WABT_ENUM_COUNT(RelocType);
+
+struct Reloc {
+ Reloc(RelocType, size_t offset, Index index, int32_t addend = 0);
+
+ RelocType type;
+ size_t offset;
+ Index index;
+ int32_t addend;
+};
+
+enum class LinkingEntryType {
+ SegmentInfo = 5,
+ InitFunctions = 6,
+ ComdatInfo = 7,
+ SymbolTable = 8,
+};
+
+enum class DylinkEntryType {
+ MemInfo = 1,
+ Needed = 2,
+ ExportInfo = 3,
+ ImportInfo = 4,
+};
+
+enum class SymbolType {
+ Function = 0,
+ Data = 1,
+ Global = 2,
+ Section = 3,
+ Tag = 4,
+ Table = 5,
+};
+
+enum class ComdatType {
+ Data = 0x0,
+ Function = 0x1,
+};
+
+#define WABT_SYMBOL_MASK_VISIBILITY 0x4
+#define WABT_SYMBOL_MASK_BINDING 0x3
+#define WABT_SYMBOL_FLAG_UNDEFINED 0x10
+#define WABT_SYMBOL_FLAG_EXPORTED 0x20
+#define WABT_SYMBOL_FLAG_EXPLICIT_NAME 0x40
+#define WABT_SYMBOL_FLAG_NO_STRIP 0x80
+#define WABT_SYMBOL_FLAG_TLS 0x100
+#define WABT_SYMBOL_FLAG_MAX 0x1ff
+
+#define WABT_SEGMENT_FLAG_STRINGS 0x1
+#define WABT_SEGMENT_FLAG_TLS 0x2
+#define WABT_SEGMENT_FLAG_MAX 0xff
+
+enum class SymbolVisibility {
+ Default = 0,
+ Hidden = 4,
+};
+
+enum class SymbolBinding {
+ Global = 0,
+ Weak = 1,
+ Local = 2,
+};
+
+/* matches binary format, do not change */
+enum class ExternalKind {
+ Func = 0,
+ Table = 1,
+ Memory = 2,
+ Global = 3,
+ Tag = 4,
+
+ First = Func,
+ Last = Tag,
+};
+constexpr int kExternalKindCount = WABT_ENUM_COUNT(ExternalKind);
+
+struct Limits {
+ Limits() = default;
+ explicit Limits(uint64_t initial) : initial(initial) {}
+ Limits(uint64_t initial, uint64_t max)
+ : initial(initial), max(max), has_max(true) {}
+ Limits(uint64_t initial, uint64_t max, bool is_shared)
+ : initial(initial), max(max), has_max(true), is_shared(is_shared) {}
+ Limits(uint64_t initial, uint64_t max, bool is_shared, bool is_64)
+ : initial(initial),
+ max(max),
+ has_max(true),
+ is_shared(is_shared),
+ is_64(is_64) {}
+ Type IndexType() const { return is_64 ? Type::I64 : Type::I32; }
+
+ uint64_t initial = 0;
+ uint64_t max = 0;
+ bool has_max = false;
+ bool is_shared = false;
+ bool is_64 = false;
+};
+
+enum { WABT_USE_NATURAL_ALIGNMENT = 0xFFFFFFFFFFFFFFFF };
+
+Result ReadFile(std::string_view filename, std::vector<uint8_t>* out_data);
+
+void InitStdio();
+
+/* external kind */
+
+extern const char* g_kind_name[];
+
+static inline const char* GetKindName(ExternalKind kind) {
+ return static_cast<size_t>(kind) < kExternalKindCount
+ ? g_kind_name[static_cast<size_t>(kind)]
+ : "<error_kind>";
+}
+
+/* reloc */
+
+extern const char* g_reloc_type_name[];
+
+static inline const char* GetRelocTypeName(RelocType reloc) {
+ return static_cast<size_t>(reloc) < kRelocTypeCount
+ ? g_reloc_type_name[static_cast<size_t>(reloc)]
+ : "<error_reloc_type>";
+}
+
+/* symbol */
+
+static inline const char* GetSymbolTypeName(SymbolType type) {
+ switch (type) {
+ case SymbolType::Function:
+ return "func";
+ case SymbolType::Global:
+ return "global";
+ case SymbolType::Data:
+ return "data";
+ case SymbolType::Section:
+ return "section";
+ case SymbolType::Tag:
+ return "tag";
+ case SymbolType::Table:
+ return "table";
+ default:
+ return "<error_symbol_type>";
+ }
+}
+
+template <typename T>
+void ConvertBackslashToSlash(T begin, T end) {
+ std::replace(begin, end, '\\', '/');
+}
+
+inline void ConvertBackslashToSlash(char* s, size_t length) {
+ ConvertBackslashToSlash(s, s + length);
+}
+
+inline void ConvertBackslashToSlash(char* s) {
+ ConvertBackslashToSlash(s, strlen(s));
+}
+
+inline void ConvertBackslashToSlash(std::string* s) {
+ ConvertBackslashToSlash(s->begin(), s->end());
+}
+
+inline void SwapBytesSized(void* addr, size_t size) {
+ auto bytes = static_cast<uint8_t*>(addr);
+ for (size_t i = 0; i < size / 2; i++) {
+ std::swap(bytes[i], bytes[size - 1 - i]);
+ }
+}
+
+} // namespace wabt
+
+#endif // WABT_COMMON_H_
diff --git a/third_party/wasm2c/include/wabt/decompiler-ast.h b/third_party/wasm2c/include/wabt/decompiler-ast.h
new file mode 100644
index 0000000000..33cc26c113
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/decompiler-ast.h
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_DECOMPILER_AST_H_
+#define WABT_DECOMPILER_AST_H_
+
+#include "wabt/cast.h"
+#include "wabt/generate-names.h"
+#include "wabt/ir-util.h"
+#include "wabt/ir.h"
+
+#include <map>
+
+namespace wabt {
+
+enum class NodeType {
+ Uninitialized,
+ FlushToVars,
+ FlushedVar,
+ Statements,
+ EndReturn,
+ Decl,
+ DeclInit,
+ Expr
+};
+
+// The AST we're going to convert the standard IR into.
+struct Node {
+ NodeType ntype;
+ ExprType etype; // Only if ntype == Expr.
+ const Expr* e;
+ std::vector<Node> children;
+ // Node specific annotations.
+ union {
+ struct {
+ Index var_start, var_count; // FlushedVar/FlushToVars
+ };
+ const Var* var; // Decl/DeclInit.
+ LabelType lt; // br/br_if target.
+ } u;
+
+ Node() : ntype(NodeType::Uninitialized), etype(ExprType::Nop), e(nullptr) {}
+ Node(NodeType ntype, ExprType etype, const Expr* e, const Var* v)
+ : ntype(ntype), etype(etype), e(e) {
+ u.var = v;
+ }
+
+ // This value should really never be copied, only moved.
+ Node(const Node& rhs) = delete;
+ Node& operator=(const Node& rhs) = delete;
+
+ Node(Node&& rhs) { *this = std::move(rhs); }
+ Node& operator=(Node&& rhs) {
+ ntype = rhs.ntype;
+ // Reset ntype to avoid moved from values still being used.
+ rhs.ntype = NodeType::Uninitialized;
+ etype = rhs.etype;
+ rhs.etype = ExprType::Nop;
+ e = rhs.e;
+ std::swap(children, rhs.children);
+ u = rhs.u;
+ return *this;
+ }
+};
+
+struct AST {
+ AST(ModuleContext& mc, const Func* f) : mc(mc), f(f) {
+ if (f) {
+ mc.BeginFunc(*f);
+ for (Index i = 0; i < f->GetNumParams(); i++) {
+ auto name = "$" + IndexToAlphaName(i);
+ vars_defined.insert({name, {0, false}});
+ }
+ }
+ }
+
+ ~AST() {
+ if (f) {
+ mc.EndFunc();
+ }
+ }
+
+ // Create a new node, take nargs existing nodes on the exp stack as children.
+ Node& InsertNode(NodeType ntype, ExprType etype, const Expr* e, Index nargs) {
+ assert(exp_stack.size() >= nargs);
+ Node n{ntype, etype, e, nullptr};
+ n.children.reserve(nargs);
+ std::move(exp_stack.end() - nargs, exp_stack.end(),
+ std::back_inserter(n.children));
+ exp_stack.erase(exp_stack.end() - nargs, exp_stack.end());
+ exp_stack.push_back(std::move(n));
+ return exp_stack.back();
+ }
+
+ template <ExprType T>
+ void PreDecl(const VarExpr<T>& ve) {
+ // FIXME: this is slow, and would be better to avoid in callers.
+ // See https://github.com/WebAssembly/wabt/issues/1565
+ // And https://github.com/WebAssembly/wabt/issues/1665
+ for (auto& n : predecls) {
+ if (n.u.var->name() == ve.var.name()) {
+ return;
+ }
+ }
+ predecls.emplace_back(NodeType::Decl, ExprType::Nop, nullptr, &ve.var);
+ }
+
+ template <ExprType T>
+ void Get(const VarExpr<T>& ve, bool local) {
+ if (local) {
+ auto ret = vars_defined.insert({ve.var.name(), {cur_block_id, false}});
+ if (ret.second) {
+ // Use before def, may happen since locals are guaranteed 0.
+ PreDecl(ve);
+ } else if (blocks_closed[ret.first->second.block_id]) {
+ // This is a use of a variable that was defined in a block that has
+ // already ended. This happens rarely, but we should cater for this
+ // case by lifting it to the top scope.
+ PreDecl(ve);
+ }
+ }
+ InsertNode(NodeType::Expr, T, &ve, 0);
+ }
+
+ template <ExprType T>
+ void Set(const VarExpr<T>& ve, bool local) {
+ // Seen this var before?
+ if (local &&
+ vars_defined.insert({ve.var.name(), {cur_block_id, false}}).second) {
+ if (value_stack_depth == 1) {
+ // Top level, declare it here.
+ InsertNode(NodeType::DeclInit, ExprType::Nop, nullptr, 1).u.var =
+ &ve.var;
+ return;
+ } else {
+ // Inside exp, better leave it as assignment exp and lift the decl out.
+ PreDecl(ve);
+ }
+ }
+ InsertNode(NodeType::Expr, T, &ve, 1);
+ }
+
+ template <ExprType T>
+ void Block(const BlockExprBase<T>& be, LabelType label) {
+ mc.BeginBlock(label, be.block);
+ Construct(be.block.exprs, be.block.decl.GetNumResults(),
+ be.block.decl.GetNumParams(), false);
+ mc.EndBlock();
+ InsertNode(NodeType::Expr, T, &be, 1);
+ }
+
+ void Construct(const Expr& e) {
+ auto arity = mc.GetExprArity(e);
+ switch (e.type()) {
+ case ExprType::LocalGet: {
+ Get(*cast<LocalGetExpr>(&e), true);
+ return;
+ }
+ case ExprType::GlobalGet: {
+ Get(*cast<GlobalGetExpr>(&e), false);
+ return;
+ }
+ case ExprType::LocalSet: {
+ Set(*cast<LocalSetExpr>(&e), true);
+ return;
+ }
+ case ExprType::GlobalSet: {
+ Set(*cast<GlobalSetExpr>(&e), false);
+ return;
+ }
+ case ExprType::LocalTee: {
+ auto& lt = *cast<LocalTeeExpr>(&e);
+ Set(lt, true);
+ if (value_stack_depth == 1) { // Tee is the only thing on there.
+ Get(lt, true); // Now Set + Get instead.
+ } else {
+ // Things are above us on the stack so the Tee can't be eliminated.
+ // The Set makes this work as a Tee when consumed by a parent.
+ }
+ return;
+ }
+ case ExprType::If: {
+ auto ife = cast<IfExpr>(&e);
+ value_stack_depth--; // Condition.
+ mc.BeginBlock(LabelType::Block, ife->true_);
+ Construct(ife->true_.exprs, ife->true_.decl.GetNumResults(),
+ ife->true_.decl.GetNumParams(), false);
+ if (!ife->false_.empty()) {
+ Construct(ife->false_, ife->true_.decl.GetNumResults(),
+ ife->true_.decl.GetNumParams(), false);
+ }
+ mc.EndBlock();
+ value_stack_depth++; // Put Condition back.
+ InsertNode(NodeType::Expr, ExprType::If, &e,
+ ife->false_.empty() ? 2 : 3);
+ return;
+ }
+ case ExprType::Block: {
+ Block(*cast<BlockExpr>(&e), LabelType::Block);
+ return;
+ }
+ case ExprType::Loop: {
+ Block(*cast<LoopExpr>(&e), LabelType::Loop);
+ return;
+ }
+ case ExprType::Br: {
+ InsertNode(NodeType::Expr, ExprType::Br, &e, 0).u.lt =
+ mc.GetLabel(cast<BrExpr>(&e)->var)->label_type;
+ return;
+ }
+ case ExprType::BrIf: {
+ InsertNode(NodeType::Expr, ExprType::BrIf, &e, 1).u.lt =
+ mc.GetLabel(cast<BrIfExpr>(&e)->var)->label_type;
+ return;
+ }
+ case ExprType::BrTable: {
+ InsertNode(NodeType::Expr, ExprType::BrTable, &e, 1).u.lt =
+ mc.GetLabel(cast<BrTableExpr>(&e)->default_target)->label_type;
+ return;
+ }
+ default: {
+ InsertNode(NodeType::Expr, e.type(), &e, arity.nargs);
+ return;
+ }
+ }
+ }
+
+ void Construct(const ExprList& es,
+ Index nresults,
+ Index nparams,
+ bool is_function_body) {
+ block_stack.push_back(cur_block_id);
+ cur_block_id = blocks_closed.size();
+ blocks_closed.push_back(false);
+ auto start = exp_stack.size();
+ int value_stack_depth_start = value_stack_depth - nparams;
+ auto value_stack_in_variables = value_stack_depth;
+ bool unreachable = false;
+ for (auto& e : es) {
+ Construct(e);
+ auto arity = mc.GetExprArity(e);
+ value_stack_depth -= arity.nargs;
+ value_stack_in_variables =
+ std::min(value_stack_in_variables, value_stack_depth);
+ unreachable = unreachable || arity.unreachable;
+ assert(unreachable || value_stack_depth >= value_stack_depth_start);
+ value_stack_depth += arity.nreturns;
+ // We maintain the invariant that a value_stack_depth of N is represented
+ // by the last N exp_stack items (each of which returning exactly 1
+ // value), all exp_stack items before it return void ("statements").
+ // In particular for the wasm stack:
+ // - The values between 0 and value_stack_depth_start are part of the
+ // parent block, and not touched here.
+ // - The values from there up to value_stack_in_variables are variables
+ // to be used, representing previous statements that flushed the
+ // stack into variables.
+ // - Values on top of that up to value_stack_depth are exps returning
+ // a single value.
+ // The code below maintains the above invariants. With this in place
+ // code "falls into place" the way you expect it.
+ if (arity.nreturns != 1) {
+ auto num_vars = value_stack_in_variables - value_stack_depth_start;
+ auto num_vals = value_stack_depth - value_stack_in_variables;
+ auto GenFlushVars = [&](int nargs) {
+ auto& ftv =
+ InsertNode(NodeType::FlushToVars, ExprType::Nop, nullptr, nargs);
+ ftv.u.var_start = flushed_vars;
+ ftv.u.var_count = num_vals;
+ };
+ auto MoveStatementsBelowVars = [&](size_t amount) {
+ std::rotate(exp_stack.end() - num_vars - amount,
+ exp_stack.end() - amount, exp_stack.end());
+ };
+ auto GenFlushedVars = [&]() {
+ // Re-generate these values as vars.
+ for (int i = 0; i < num_vals; i++) {
+ auto& fv =
+ InsertNode(NodeType::FlushedVar, ExprType::Nop, nullptr, 0);
+ fv.u.var_start = flushed_vars++;
+ fv.u.var_count = 1;
+ }
+ };
+ if (arity.nreturns == 0 &&
+ value_stack_depth > value_stack_depth_start) {
+ // We have a void item on top of the exp_stack, so we must "lift" the
+ // previous values around it.
+ // We track what part of the stack is in variables to avoid doing
+ // this unnecessarily.
+ if (num_vals > 0) {
+ // We have actual new values that need lifting.
+ // This puts the part of the stack that wasn't already a variable
+ // (before the current void exp) into a FlushToVars.
+ auto void_exp = std::move(exp_stack.back());
+ exp_stack.pop_back();
+ GenFlushVars(num_vals);
+ exp_stack.push_back(std::move(void_exp));
+ // Put this flush statement + void statement before any
+ // existing variables.
+ MoveStatementsBelowVars(2);
+ // Now re-generate these values after the void exp as vars.
+ GenFlushedVars();
+ } else {
+ // We have existing variables that need lifting, but no need to
+ // create them anew.
+ std::rotate(exp_stack.end() - num_vars - 1, exp_stack.end() - 1,
+ exp_stack.end());
+ }
+ value_stack_in_variables = value_stack_depth;
+ } else if (arity.nreturns > 1) {
+ // Multivalue: we flush the stack also.
+ // Number of other non-variable values that may be present:
+ assert(num_vals >= static_cast<int>(arity.nreturns));
+ // Flush multi-value exp + others.
+ GenFlushVars(num_vals - arity.nreturns + 1);
+ // Put this flush statement before any existing variables.
+ MoveStatementsBelowVars(1);
+ GenFlushedVars();
+ value_stack_in_variables = value_stack_depth;
+ }
+ } else {
+ // Special optimisation: for constant instructions, we can mark these
+ // as if they were variables, so they can be re-ordered for free with
+ // the above code, without needing new variables!
+ // TODO: this would be nice to also do for local.get and maybe others,
+ // though that needs a way to ensure there's no local.set in between
+ // when they get lifted, so complicates matters a bit.
+ if (e.type() == ExprType::Const &&
+ value_stack_in_variables == value_stack_depth - 1) {
+ value_stack_in_variables++;
+ }
+ }
+ }
+ assert(unreachable || value_stack_depth - value_stack_depth_start ==
+ static_cast<int>(nresults));
+ // Undo any changes to value_stack_depth, since parent takes care of arity
+ // changes.
+ value_stack_depth = value_stack_depth_start;
+ auto end = exp_stack.size();
+ assert(end >= start);
+ if (is_function_body) {
+ if (!exp_stack.empty()) {
+ if (exp_stack.back().etype == ExprType::Return) {
+ if (exp_stack.back().children.empty()) {
+ // Return statement at the end of a void function.
+ exp_stack.pop_back();
+ }
+ } else if (nresults) {
+ // Combine nresults into a return statement, for when this is used as
+ // a function body.
+ // TODO: if this is some other kind of block and >1 value is being
+ // returned, probably need some kind of syntax to make that clearer.
+ InsertNode(NodeType::EndReturn, ExprType::Nop, nullptr, nresults);
+ }
+ }
+ // TODO: these predecls are always at top level, but in the case of
+ // use inside an exp, it be nice to do it in the current block. Can't
+ // do that for predecls that are "out if scope" however.
+ std::move(predecls.begin(), predecls.end(),
+ std::back_inserter(exp_stack));
+ std::rotate(exp_stack.begin(), exp_stack.end() - predecls.size(),
+ exp_stack.end());
+ predecls.clear();
+ }
+ end = exp_stack.size();
+ assert(end >= start);
+ auto size = end - start;
+ if (size != 1) {
+ InsertNode(NodeType::Statements, ExprType::Nop, nullptr, size);
+ }
+ blocks_closed[cur_block_id] = true;
+ cur_block_id = block_stack.back();
+ block_stack.pop_back();
+ }
+
+ ModuleContext& mc;
+ std::vector<Node> exp_stack;
+ std::vector<Node> predecls;
+ const Func* f;
+ int value_stack_depth = 0;
+ struct Variable {
+ size_t block_id;
+ bool defined;
+ };
+ std::map<std::string, Variable> vars_defined;
+ Index flushed_vars = 0;
+ size_t cur_block_id = 0;
+ std::vector<size_t> block_stack;
+ std::vector<bool> blocks_closed;
+};
+
+} // namespace wabt
+
+#endif // WABT_DECOMPILER_AST_H_
diff --git a/third_party/wasm2c/include/wabt/decompiler-ls.h b/third_party/wasm2c/include/wabt/decompiler-ls.h
new file mode 100644
index 0000000000..c2612fa32a
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/decompiler-ls.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#ifndef WABT_DECOMPILER_LS_H_
+#define WABT_DECOMPILER_LS_H_
+
+#include "wabt/decompiler-ast.h"
+#include "wabt/string-util.h"
+
+#include <map>
+
+namespace wabt {
+
+// Names starting with "u" are unsigned, the rest are "signed or doesn't matter"
+inline const char* GetDecompTypeName(Type t) {
+ switch (t) {
+ case Type::I8: return "byte";
+ case Type::I8U: return "ubyte";
+ case Type::I16: return "short";
+ case Type::I16U: return "ushort";
+ case Type::I32: return "int";
+ case Type::I32U: return "uint";
+ case Type::I64: return "long";
+ case Type::F32: return "float";
+ case Type::F64: return "double";
+ case Type::V128: return "simd";
+ case Type::Func: return "func";
+ case Type::FuncRef: return "funcref";
+ case Type::ExternRef: return "externref";
+ case Type::Void: return "void";
+ default: return "ILLEGAL";
+ }
+}
+
+inline Type GetMemoryType(Type operand_type, Opcode opc) {
+ // TODO: something something SIMD.
+ // TODO: this loses information of the type it is read into.
+ // That may well not be the biggest deal since that is usually obvious
+ // from context, if not, we should probably represent that as a cast around
+ // the access, since it should not be part of the field type.
+ if (operand_type == Type::I32 || operand_type == Type::I64) {
+ auto name = std::string_view(opc.GetName());
+ // FIXME: change into a new column in opcode.def instead?
+ auto is_unsigned = name.substr(name.size() - 2) == "_u";
+ switch (opc.GetMemorySize()) {
+ case 1: return is_unsigned ? Type::I8U : Type::I8;
+ case 2: return is_unsigned ? Type::I16U : Type::I16;
+ case 4: return is_unsigned ? Type::I32U : Type::I32;
+ }
+ }
+ return operand_type;
+}
+
+// Track all loads and stores inside a single function, to be able to detect
+// struct layouts we can use to annotate variables with, to make code more
+// readable.
+struct LoadStoreTracking {
+ struct LSAccess {
+ Address byte_size = 0;
+ Type type = Type::Any;
+ Address align = 0;
+ uint32_t idx = 0;
+ bool is_uniform = true;
+ };
+
+ struct LSVar {
+ std::map<uint64_t, LSAccess> accesses;
+ bool struct_layout = true;
+ Type same_type = Type::Any;
+ Address same_align = kInvalidAddress;
+ Opcode last_opc;
+ };
+
+ void Track(const Node& n) {
+ for (auto& c : n.children) {
+ Track(c);
+ }
+ switch (n.etype) {
+ case ExprType::Load: {
+ auto& le = *cast<LoadExpr>(n.e);
+ LoadStore(le.offset, le.opcode, le.opcode.GetResultType(), le.align,
+ n.children[0]);
+ break;
+ }
+ case ExprType::Store: {
+ auto& se = *cast<StoreExpr>(n.e);
+ LoadStore(se.offset, se.opcode, se.opcode.GetParamType2(), se.align,
+ n.children[0]);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ const std::string AddrExpName(const Node& addr_exp) const {
+ // TODO: expand this to more kinds of address expressions.
+ switch (addr_exp.etype) {
+ case ExprType::LocalGet:
+ return cast<LocalGetExpr>(addr_exp.e)->var.name();
+ break;
+ case ExprType::LocalTee:
+ return cast<LocalTeeExpr>(addr_exp.e)->var.name();
+ break;
+ default:
+ return "";
+ }
+ }
+
+ void LoadStore(uint64_t offset,
+ Opcode opc,
+ Type type,
+ Address align,
+ const Node& addr_exp) {
+ auto byte_size = opc.GetMemorySize();
+ type = GetMemoryType(type, opc);
+ // We want to associate memory ops of a certain offset & size as being
+ // relative to a uniquely identifiable pointer, such as a local.
+ auto name = AddrExpName(addr_exp);
+ if (name.empty()) {
+ return;
+ }
+ auto& var = vars[name];
+ auto& access = var.accesses[offset];
+ // Check if previous access at this offset (if any) is of same size
+ // and type (see Checklayouts below).
+ if (access.byte_size && ((access.byte_size != byte_size) ||
+ (access.type != type) || (access.align != align)))
+ access.is_uniform = false;
+ // Also exclude weird alignment accesses from structs.
+ if (!opc.IsNaturallyAligned(align))
+ access.is_uniform = false;
+ access.byte_size = byte_size;
+ access.type = type;
+ access.align = align;
+ // Additionally, check if all accesses are to the same type, so
+ // if layout check fails, we can at least declare it as pointer to
+ // a type.
+ if ((var.same_type == type || var.same_type == Type::Any) &&
+ (var.same_align == align || var.same_align == kInvalidAddress)) {
+ var.same_type = type;
+ var.same_align = align;
+ var.last_opc = opc;
+ } else {
+ var.same_type = Type::Void;
+ var.same_align = kInvalidAddress;
+ }
+ }
+
+ void CheckLayouts() {
+ // Here we check if the set of accesses we have collected form a sequence
+ // we could declare as a struct, meaning they are properly aligned,
+ // contiguous, and have no overlaps between different types and sizes.
+ // We do this because an int access of size 2 at offset 0 followed by
+ // a float access of size 4 at offset 4 can compactly represented as a
+ // struct { short, float }, whereas something that reads from overlapping
+ // or discontinuous offsets would need a more complicated syntax that
+ // involves explicit offsets.
+ // We assume that the bulk of memory accesses are of this very regular kind,
+ // so we choose not to even emit struct layouts for irregular ones,
+ // given that they are rare and confusing, and thus do not benefit from
+ // being represented as if they were structs.
+ for (auto& var : vars) {
+ if (var.second.accesses.size() == 1) {
+ // If we have just one access, this is better represented as a pointer
+ // than a struct.
+ var.second.struct_layout = false;
+ continue;
+ }
+ uint64_t cur_offset = 0;
+ uint32_t idx = 0;
+ for (auto& access : var.second.accesses) {
+ access.second.idx = idx++;
+ if (!access.second.is_uniform) {
+ var.second.struct_layout = false;
+ break;
+ }
+ // Align to next access: all elements are expected to be aligned to
+ // a memory address thats a multiple of their own size.
+ auto mask = static_cast<uint64_t>(access.second.byte_size - 1);
+ cur_offset = (cur_offset + mask) & ~mask;
+ if (cur_offset != access.first) {
+ var.second.struct_layout = false;
+ break;
+ }
+ cur_offset += access.second.byte_size;
+ }
+ }
+ }
+
+ std::string IdxToName(uint32_t idx) const {
+ return IndexToAlphaName(idx); // TODO: more descriptive names?
+ }
+
+ std::string GenAlign(Address align, Opcode opc) const {
+ return opc.IsNaturallyAligned(align) ? "" : cat("@", std::to_string(align));
+ }
+
+ std::string GenTypeDecl(const std::string& name) const {
+ auto it = vars.find(name);
+ if (it == vars.end()) {
+ return "";
+ }
+ if (it->second.struct_layout) {
+ std::string s = "{ ";
+ for (auto& access : it->second.accesses) {
+ if (access.second.idx) {
+ s += ", ";
+ }
+ s += IdxToName(access.second.idx);
+ s += ':';
+ s += GetDecompTypeName(access.second.type);
+ }
+ s += " }";
+ return s;
+ }
+ // We don't have a struct layout, or the struct has just one field,
+ // so maybe we can just declare it as a pointer to one type?
+ if (it->second.same_type != Type::Void) {
+ return cat(GetDecompTypeName(it->second.same_type), "_ptr",
+ GenAlign(it->second.same_align, it->second.last_opc));
+ }
+ return "";
+ }
+
+ std::string GenAccess(uint64_t offset, const Node& addr_exp) const {
+ auto name = AddrExpName(addr_exp);
+ if (name.empty()) {
+ return "";
+ }
+ auto it = vars.find(name);
+ if (it == vars.end()) {
+ return "";
+ }
+ if (it->second.struct_layout) {
+ auto ait = it->second.accesses.find(offset);
+ assert(ait != it->second.accesses.end());
+ return IdxToName(ait->second.idx);
+ }
+ // Not a struct, see if it is a typed pointer.
+ if (it->second.same_type != Type::Void) {
+ return "*";
+ }
+ return "";
+ }
+
+ void Clear() { vars.clear(); }
+
+ std::map<std::string, LSVar> vars;
+};
+
+} // namespace wabt
+
+#endif // WABT_DECOMPILER_LS_H_
diff --git a/third_party/wasm2c/include/wabt/decompiler-naming.h b/third_party/wasm2c/include/wabt/decompiler-naming.h
new file mode 100644
index 0000000000..12c40e04fc
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/decompiler-naming.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2019 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.
+ */
+
+#ifndef WABT_DECOMPILER_NAMING_H_
+#define WABT_DECOMPILER_NAMING_H_
+
+#include "wabt/decompiler-ast.h"
+
+#include <set>
+
+namespace wabt {
+
+inline void RenameToIdentifier(std::string& name,
+ Index i,
+ BindingHash& bh,
+ const std::set<std::string_view>* filter) {
+ // Filter out non-identifier characters, and try to reduce the size of
+ // gigantic C++ signature names.
+ std::string s;
+ size_t nesting = 0;
+ size_t read = 0;
+ size_t word_start = 0;
+ for (auto c : name) {
+ read++;
+ // We most certainly don't want to parse the entirety of C++ signatures,
+ // but these names are sometimes several lines long, so would be great
+ // to trim down. One quick way to do that is to remove anything between
+ // nested (), which usually means the parameter list.
+ if (c == '(') {
+ nesting++;
+ }
+ if (c == ')') {
+ nesting--;
+ }
+ if (nesting) {
+ continue;
+ }
+ if (!isalnum(static_cast<unsigned char>(c))) {
+ c = '_';
+ }
+ if (c == '_') {
+ if (s.empty()) {
+ continue; // Skip leading.
+ }
+ if (s.back() == '_') {
+ continue; // Consecutive.
+ }
+ }
+ s += c;
+ if (filter && (c == '_' || read == name.size())) {
+ // We found a "word" inside a snake_case identifier.
+ auto word_end = s.size();
+ if (c == '_') {
+ word_end--;
+ }
+ assert(word_end > word_start);
+ auto word =
+ std::string_view(s.c_str() + word_start, word_end - word_start);
+ if (filter->find(word) != filter->end()) {
+ s.resize(word_start);
+ }
+ word_start = s.size();
+ }
+ }
+ if (!s.empty() && s.back() == '_') {
+ s.pop_back(); // Trailing.
+ }
+ // If after all this culling, we're still gigantic (STL identifier can
+ // easily be hundreds of chars in size), just cut the identifier
+ // down, it will be disambiguated below, if needed.
+ const size_t max_identifier_length = 100;
+ if (s.size() > max_identifier_length) {
+ s.resize(max_identifier_length);
+ }
+ if (s.empty()) {
+ s = "__empty";
+ }
+ // Remove original binding first, such that it doesn't match with our
+ // new name.
+ bh.erase(name);
+ // Find a unique name.
+ Index disambiguator = 0;
+ auto base_len = s.size();
+ for (;;) {
+ if (bh.count(s) == 0) {
+ break;
+ }
+ disambiguator++;
+ s.resize(base_len);
+ s += '_';
+ s += std::to_string(disambiguator);
+ }
+ // Replace name in bindings.
+ name = s;
+ bh.emplace(s, Binding(i));
+}
+
+template <typename T>
+void RenameToIdentifiers(std::vector<T*>& things,
+ BindingHash& bh,
+ const std::set<std::string_view>* filter) {
+ Index i = 0;
+ for (auto thing : things) {
+ RenameToIdentifier(thing->name, i++, bh, filter);
+ }
+}
+
+enum {
+ // This a bit arbitrary, change at will.
+ min_content_identifier_size = 7,
+ max_content_identifier_size = 30
+};
+
+void RenameToContents(std::vector<DataSegment*>& segs, BindingHash& bh) {
+ std::string s;
+ for (auto seg : segs) {
+ if (seg->name.substr(0, 2) != "d_") {
+ // This segment was named explicitly by a symbol.
+ // FIXME: this is not a great check, a symbol could start with d_.
+ continue;
+ }
+ s = "d_";
+ for (auto c : seg->data) {
+ if (isalnum(c) || c == '_') {
+ s += static_cast<char>(c);
+ }
+ if (s.size() >= max_content_identifier_size) {
+ // We truncate any very long names, since those make for hard to
+ // format output. They can be somewhat long though, since data segment
+ // references tend to not occur that often.
+ break;
+ }
+ }
+ if (s.size() < min_content_identifier_size) {
+ // It is useful to have a minimum, since if there few printable characters
+ // in a data section, that is probably a sign of binary, and those few
+ // characters are not going to be very significant.
+ continue;
+ }
+ // We could do the same disambiguition as RenameToIdentifier and
+ // GenerateNames do, but if we come up with a clashing name here it is
+ // likely a sign of not very meaningful binary data, so it is easier to
+ // just keep the original generated name in that case.
+ if (bh.count(s) != 0) {
+ continue;
+ }
+ // Remove original entry.
+ bh.erase(seg->name);
+ seg->name = s;
+ bh.emplace(s, Binding(static_cast<Index>(&seg - &segs[0])));
+ }
+}
+
+// Function names may contain arbitrary C++ syntax, so we want to
+// filter those to look like identifiers. A function name may be set
+// by a name section (applied in ReadBinaryIr, called before this function)
+// or by an export (applied by GenerateNames, called before this function),
+// to both the Func and func_bindings.
+// Those names then further perculate down the IR in ApplyNames (called after
+// this function).
+// To not have to add too many decompiler-specific code into those systems
+// (using a callback??) we instead rename everything here.
+// Also do data section renaming here.
+void RenameAll(Module& module) {
+ // We also filter common C++ keywords/STL idents that make for huge
+ // identifiers.
+ // FIXME: this can obviously give bad results if the input is not C++..
+ std::set<std::string_view> filter = {
+ {"const"}, {"std"}, {"allocator"}, {"char"}, {"basic"},
+ {"traits"}, {"wchar"}, {"t"}, {"void"}, {"int"},
+ {"unsigned"}, {"2"}, {"cxxabiv1"}, {"short"}, {"4096ul"},
+ };
+ RenameToIdentifiers(module.funcs, module.func_bindings, &filter);
+ // Also do this for some other kinds of names, but without the keyword
+ // substitution.
+ RenameToIdentifiers(module.globals, module.global_bindings, nullptr);
+ RenameToIdentifiers(module.tables, module.table_bindings, nullptr);
+ RenameToIdentifiers(module.tags, module.tag_bindings, nullptr);
+ RenameToIdentifiers(module.exports, module.export_bindings, nullptr);
+ RenameToIdentifiers(module.types, module.type_bindings, nullptr);
+ RenameToIdentifiers(module.memories, module.memory_bindings, nullptr);
+ RenameToIdentifiers(module.data_segments, module.data_segment_bindings,
+ nullptr);
+ RenameToIdentifiers(module.elem_segments, module.elem_segment_bindings,
+ nullptr);
+ // Special purpose naming for data segments.
+ RenameToContents(module.data_segments, module.data_segment_bindings);
+}
+
+} // namespace wabt
+
+#endif // WABT_DECOMPILER_NAMING_H_
diff --git a/third_party/wasm2c/include/wabt/decompiler.h b/third_party/wasm2c/include/wabt/decompiler.h
new file mode 100644
index 0000000000..375a4b0371
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/decompiler.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_DECOMPILER_H_
+#define WABT_DECOMPILER_H_
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+struct Module;
+class Stream;
+
+struct DecompileOptions {};
+
+void RenameAll(Module&);
+
+std::string Decompile(const Module&, const DecompileOptions&);
+
+} // namespace wabt
+
+#endif /* WABT_DECOMPILER_H_ */
diff --git a/third_party/wasm2c/include/wabt/error-formatter.h b/third_party/wasm2c/include/wabt/error-formatter.h
new file mode 100644
index 0000000000..a66c57ab0c
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/error-formatter.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_ERROR_FORMATTER_H_
+#define WABT_ERROR_FORMATTER_H_
+
+#include <cstdio>
+#include <memory>
+#include <string>
+
+#include "wabt/color.h"
+#include "wabt/error.h"
+#include "wabt/lexer-source-line-finder.h"
+
+namespace wabt {
+
+enum class PrintHeader {
+ Never,
+ Once,
+ Always,
+};
+
+std::string FormatErrorsToString(const Errors&,
+ Location::Type,
+ LexerSourceLineFinder* = nullptr,
+ const Color& color = Color(nullptr, false),
+ const std::string& header = {},
+ PrintHeader print_header = PrintHeader::Never,
+ int source_line_max_length = 80);
+
+void FormatErrorsToFile(const Errors&,
+ Location::Type,
+ LexerSourceLineFinder* = nullptr,
+ FILE* = stderr,
+ const std::string& header = {},
+ PrintHeader print_header = PrintHeader::Never,
+ int source_line_max_length = 80);
+
+} // namespace wabt
+
+#endif // WABT_ERROR_FORMATTER_H_
diff --git a/third_party/wasm2c/include/wabt/error.h b/third_party/wasm2c/include/wabt/error.h
new file mode 100644
index 0000000000..d16e1e6559
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/error.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_ERROR_H_
+#define WABT_ERROR_H_
+
+#include <string>
+#include <string_view>
+#include <vector>
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+enum class ErrorLevel {
+ Warning,
+ Error,
+};
+
+static inline const char* GetErrorLevelName(ErrorLevel error_level) {
+ switch (error_level) {
+ case ErrorLevel::Warning:
+ return "warning";
+ case ErrorLevel::Error:
+ return "error";
+ }
+ WABT_UNREACHABLE;
+}
+
+class Error {
+ public:
+ Error() : error_level(ErrorLevel::Error) {}
+ Error(ErrorLevel error_level, Location loc, std::string_view message)
+ : error_level(error_level), loc(loc), message(message) {}
+
+ ErrorLevel error_level;
+ Location loc;
+ std::string message;
+};
+
+using Errors = std::vector<Error>;
+
+} // namespace wabt
+
+#endif // WABT_ERROR_H_
diff --git a/third_party/wasm2c/include/wabt/expr-visitor.h b/third_party/wasm2c/include/wabt/expr-visitor.h
new file mode 100644
index 0000000000..cbc317cde5
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/expr-visitor.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_EXPR_VISITOR_H_
+#define WABT_EXPR_VISITOR_H_
+
+#include "wabt/common.h"
+#include "wabt/ir.h"
+
+namespace wabt {
+
+class ExprVisitor {
+ public:
+ class Delegate;
+ class DelegateNop;
+
+ explicit ExprVisitor(Delegate* delegate);
+
+ Result VisitExpr(Expr*);
+ Result VisitExprList(ExprList&);
+ Result VisitFunc(Func*);
+
+ private:
+ enum class State {
+ Default,
+ Block,
+ IfTrue,
+ IfFalse,
+ Loop,
+ Try,
+ Catch,
+ };
+
+ Result HandleDefaultState(Expr*);
+ void PushDefault(Expr*);
+ void PopDefault();
+ void PushExprlist(State state, Expr*, ExprList&);
+ void PopExprlist();
+ void PushCatch(Expr*, Index catch_index, ExprList&);
+ void PopCatch();
+
+ Delegate* delegate_;
+
+ // Use parallel arrays instead of array of structs so we can avoid allocating
+ // unneeded objects. ExprList::iterator has no default constructor, so it
+ // must only be allocated for states that use it.
+ std::vector<State> state_stack_;
+ std::vector<Expr*> expr_stack_;
+ std::vector<ExprList::iterator> expr_iter_stack_;
+ std::vector<Index> catch_index_stack_;
+};
+
+class ExprVisitor::Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ virtual Result OnBinaryExpr(BinaryExpr*) = 0;
+ virtual Result BeginBlockExpr(BlockExpr*) = 0;
+ virtual Result EndBlockExpr(BlockExpr*) = 0;
+ virtual Result OnBrExpr(BrExpr*) = 0;
+ virtual Result OnBrIfExpr(BrIfExpr*) = 0;
+ virtual Result OnBrTableExpr(BrTableExpr*) = 0;
+ virtual Result OnCallExpr(CallExpr*) = 0;
+ virtual Result OnCallIndirectExpr(CallIndirectExpr*) = 0;
+ virtual Result OnCallRefExpr(CallRefExpr*) = 0;
+ virtual Result OnCodeMetadataExpr(CodeMetadataExpr*) = 0;
+ virtual Result OnCompareExpr(CompareExpr*) = 0;
+ virtual Result OnConstExpr(ConstExpr*) = 0;
+ virtual Result OnConvertExpr(ConvertExpr*) = 0;
+ virtual Result OnDropExpr(DropExpr*) = 0;
+ virtual Result OnGlobalGetExpr(GlobalGetExpr*) = 0;
+ virtual Result OnGlobalSetExpr(GlobalSetExpr*) = 0;
+ virtual Result BeginIfExpr(IfExpr*) = 0;
+ virtual Result AfterIfTrueExpr(IfExpr*) = 0;
+ virtual Result EndIfExpr(IfExpr*) = 0;
+ virtual Result OnLoadExpr(LoadExpr*) = 0;
+ virtual Result OnLocalGetExpr(LocalGetExpr*) = 0;
+ virtual Result OnLocalSetExpr(LocalSetExpr*) = 0;
+ virtual Result OnLocalTeeExpr(LocalTeeExpr*) = 0;
+ virtual Result BeginLoopExpr(LoopExpr*) = 0;
+ virtual Result EndLoopExpr(LoopExpr*) = 0;
+ virtual Result OnMemoryCopyExpr(MemoryCopyExpr*) = 0;
+ virtual Result OnDataDropExpr(DataDropExpr*) = 0;
+ virtual Result OnMemoryFillExpr(MemoryFillExpr*) = 0;
+ virtual Result OnMemoryGrowExpr(MemoryGrowExpr*) = 0;
+ virtual Result OnMemoryInitExpr(MemoryInitExpr*) = 0;
+ virtual Result OnMemorySizeExpr(MemorySizeExpr*) = 0;
+ virtual Result OnTableCopyExpr(TableCopyExpr*) = 0;
+ virtual Result OnElemDropExpr(ElemDropExpr*) = 0;
+ virtual Result OnTableInitExpr(TableInitExpr*) = 0;
+ virtual Result OnTableGetExpr(TableGetExpr*) = 0;
+ virtual Result OnTableSetExpr(TableSetExpr*) = 0;
+ virtual Result OnTableGrowExpr(TableGrowExpr*) = 0;
+ virtual Result OnTableSizeExpr(TableSizeExpr*) = 0;
+ virtual Result OnTableFillExpr(TableFillExpr*) = 0;
+ virtual Result OnRefFuncExpr(RefFuncExpr*) = 0;
+ virtual Result OnRefNullExpr(RefNullExpr*) = 0;
+ virtual Result OnRefIsNullExpr(RefIsNullExpr*) = 0;
+ virtual Result OnNopExpr(NopExpr*) = 0;
+ virtual Result OnReturnExpr(ReturnExpr*) = 0;
+ virtual Result OnReturnCallExpr(ReturnCallExpr*) = 0;
+ virtual Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) = 0;
+ virtual Result OnSelectExpr(SelectExpr*) = 0;
+ virtual Result OnStoreExpr(StoreExpr*) = 0;
+ virtual Result OnUnaryExpr(UnaryExpr*) = 0;
+ virtual Result OnUnreachableExpr(UnreachableExpr*) = 0;
+ virtual Result BeginTryExpr(TryExpr*) = 0;
+ virtual Result OnCatchExpr(TryExpr*, Catch*) = 0;
+ virtual Result OnDelegateExpr(TryExpr*) = 0;
+ virtual Result EndTryExpr(TryExpr*) = 0;
+ virtual Result OnThrowExpr(ThrowExpr*) = 0;
+ virtual Result OnRethrowExpr(RethrowExpr*) = 0;
+ virtual Result OnAtomicWaitExpr(AtomicWaitExpr*) = 0;
+ virtual Result OnAtomicFenceExpr(AtomicFenceExpr*) = 0;
+ virtual Result OnAtomicNotifyExpr(AtomicNotifyExpr*) = 0;
+ virtual Result OnAtomicLoadExpr(AtomicLoadExpr*) = 0;
+ virtual Result OnAtomicStoreExpr(AtomicStoreExpr*) = 0;
+ virtual Result OnAtomicRmwExpr(AtomicRmwExpr*) = 0;
+ virtual Result OnAtomicRmwCmpxchgExpr(AtomicRmwCmpxchgExpr*) = 0;
+ virtual Result OnTernaryExpr(TernaryExpr*) = 0;
+ virtual Result OnSimdLaneOpExpr(SimdLaneOpExpr*) = 0;
+ virtual Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) = 0;
+ virtual Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) = 0;
+ virtual Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) = 0;
+ virtual Result OnLoadSplatExpr(LoadSplatExpr*) = 0;
+ virtual Result OnLoadZeroExpr(LoadZeroExpr*) = 0;
+};
+
+class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
+ public:
+ Result OnBinaryExpr(BinaryExpr*) override { return Result::Ok; }
+ Result BeginBlockExpr(BlockExpr*) override { return Result::Ok; }
+ Result EndBlockExpr(BlockExpr*) override { return Result::Ok; }
+ Result OnBrExpr(BrExpr*) override { return Result::Ok; }
+ Result OnBrIfExpr(BrIfExpr*) override { return Result::Ok; }
+ Result OnBrTableExpr(BrTableExpr*) override { return Result::Ok; }
+ Result OnCallExpr(CallExpr*) override { return Result::Ok; }
+ Result OnCallIndirectExpr(CallIndirectExpr*) override { return Result::Ok; }
+ Result OnCallRefExpr(CallRefExpr*) override { return Result::Ok; }
+ Result OnCodeMetadataExpr(CodeMetadataExpr*) override { return Result::Ok; }
+ Result OnCompareExpr(CompareExpr*) override { return Result::Ok; }
+ Result OnConstExpr(ConstExpr*) override { return Result::Ok; }
+ Result OnConvertExpr(ConvertExpr*) override { return Result::Ok; }
+ Result OnDropExpr(DropExpr*) override { return Result::Ok; }
+ Result OnGlobalGetExpr(GlobalGetExpr*) override { return Result::Ok; }
+ Result OnGlobalSetExpr(GlobalSetExpr*) override { return Result::Ok; }
+ Result BeginIfExpr(IfExpr*) override { return Result::Ok; }
+ Result AfterIfTrueExpr(IfExpr*) override { return Result::Ok; }
+ Result EndIfExpr(IfExpr*) override { return Result::Ok; }
+ Result OnLoadExpr(LoadExpr*) override { return Result::Ok; }
+ Result OnLocalGetExpr(LocalGetExpr*) override { return Result::Ok; }
+ Result OnLocalSetExpr(LocalSetExpr*) override { return Result::Ok; }
+ Result OnLocalTeeExpr(LocalTeeExpr*) override { return Result::Ok; }
+ Result BeginLoopExpr(LoopExpr*) override { return Result::Ok; }
+ Result EndLoopExpr(LoopExpr*) override { return Result::Ok; }
+ Result OnMemoryCopyExpr(MemoryCopyExpr*) override { return Result::Ok; }
+ Result OnDataDropExpr(DataDropExpr*) override { return Result::Ok; }
+ Result OnMemoryFillExpr(MemoryFillExpr*) override { return Result::Ok; }
+ Result OnMemoryGrowExpr(MemoryGrowExpr*) override { return Result::Ok; }
+ Result OnMemoryInitExpr(MemoryInitExpr*) override { return Result::Ok; }
+ Result OnMemorySizeExpr(MemorySizeExpr*) override { return Result::Ok; }
+ Result OnTableCopyExpr(TableCopyExpr*) override { return Result::Ok; }
+ Result OnElemDropExpr(ElemDropExpr*) override { return Result::Ok; }
+ Result OnTableInitExpr(TableInitExpr*) override { return Result::Ok; }
+ Result OnTableGetExpr(TableGetExpr*) override { return Result::Ok; }
+ Result OnTableSetExpr(TableSetExpr*) override { return Result::Ok; }
+ Result OnTableGrowExpr(TableGrowExpr*) override { return Result::Ok; }
+ Result OnTableSizeExpr(TableSizeExpr*) override { return Result::Ok; }
+ Result OnTableFillExpr(TableFillExpr*) override { return Result::Ok; }
+ Result OnRefFuncExpr(RefFuncExpr*) override { return Result::Ok; }
+ Result OnRefNullExpr(RefNullExpr*) override { return Result::Ok; }
+ Result OnRefIsNullExpr(RefIsNullExpr*) override { return Result::Ok; }
+ Result OnNopExpr(NopExpr*) override { return Result::Ok; }
+ Result OnReturnExpr(ReturnExpr*) override { return Result::Ok; }
+ Result OnReturnCallExpr(ReturnCallExpr*) override { return Result::Ok; }
+ Result OnReturnCallIndirectExpr(ReturnCallIndirectExpr*) override {
+ return Result::Ok;
+ }
+ Result OnSelectExpr(SelectExpr*) override { return Result::Ok; }
+ Result OnStoreExpr(StoreExpr*) override { return Result::Ok; }
+ Result OnUnaryExpr(UnaryExpr*) override { return Result::Ok; }
+ Result OnUnreachableExpr(UnreachableExpr*) override { return Result::Ok; }
+ Result BeginTryExpr(TryExpr*) override { return Result::Ok; }
+ Result OnCatchExpr(TryExpr*, Catch*) override { return Result::Ok; }
+ Result OnDelegateExpr(TryExpr*) override { return Result::Ok; }
+ Result EndTryExpr(TryExpr*) override { return Result::Ok; }
+ Result OnThrowExpr(ThrowExpr*) override { return Result::Ok; }
+ Result OnRethrowExpr(RethrowExpr*) override { return Result::Ok; }
+ Result OnAtomicWaitExpr(AtomicWaitExpr*) override { return Result::Ok; }
+ Result OnAtomicFenceExpr(AtomicFenceExpr*) override { return Result::Ok; }
+ Result OnAtomicNotifyExpr(AtomicNotifyExpr*) override { return Result::Ok; }
+ Result OnAtomicLoadExpr(AtomicLoadExpr*) override { return Result::Ok; }
+ Result OnAtomicStoreExpr(AtomicStoreExpr*) override { return Result::Ok; }
+ Result OnAtomicRmwExpr(AtomicRmwExpr*) override { return Result::Ok; }
+ Result OnAtomicRmwCmpxchgExpr(AtomicRmwCmpxchgExpr*) override {
+ return Result::Ok;
+ }
+ Result OnTernaryExpr(TernaryExpr*) override { return Result::Ok; }
+ Result OnSimdLaneOpExpr(SimdLaneOpExpr*) override { return Result::Ok; }
+ Result OnSimdLoadLaneExpr(SimdLoadLaneExpr*) override { return Result::Ok; }
+ Result OnSimdStoreLaneExpr(SimdStoreLaneExpr*) override { return Result::Ok; }
+ Result OnSimdShuffleOpExpr(SimdShuffleOpExpr*) override { return Result::Ok; }
+ Result OnLoadSplatExpr(LoadSplatExpr*) override { return Result::Ok; }
+ Result OnLoadZeroExpr(LoadZeroExpr*) override { return Result::Ok; }
+};
+
+} // namespace wabt
+
+#endif // WABT_EXPR_VISITOR_H_
diff --git a/third_party/wasm2c/include/wabt/feature.def b/third_party/wasm2c/include/wabt/feature.def
new file mode 100644
index 0000000000..00a4e7f238
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/feature.def
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_FEATURE
+#error "You must define WABT_FEATURE before including this file."
+#endif
+
+/*
+ * variable flag default help
+ * ========================================================================= */
+
+WABT_FEATURE(exceptions, "exceptions", false, "Experimental exception handling")
+WABT_FEATURE(mutable_globals, "mutable-globals", true, "Import/export mutable globals")
+WABT_FEATURE(sat_float_to_int, "saturating-float-to-int", true, "Saturating float-to-int operators")
+WABT_FEATURE(sign_extension, "sign-extension", true, "Sign-extension operators")
+WABT_FEATURE(simd, "simd", true, "SIMD support")
+WABT_FEATURE(threads, "threads", false, "Threading support")
+WABT_FEATURE(function_references, "function-references", false, "Typed function references")
+WABT_FEATURE(multi_value, "multi-value", true, "Multi-value")
+WABT_FEATURE(tail_call, "tail-call", false, "Tail-call support")
+WABT_FEATURE(bulk_memory, "bulk-memory", true, "Bulk-memory operations")
+WABT_FEATURE(reference_types, "reference-types", true, "Reference types (externref)")
+WABT_FEATURE(annotations, "annotations", false, "Custom annotation syntax")
+WABT_FEATURE(code_metadata, "code-metadata", false, "Code metadata")
+WABT_FEATURE(gc, "gc", false, "Garbage collection")
+WABT_FEATURE(memory64, "memory64", false, "64-bit memory")
+WABT_FEATURE(multi_memory, "multi-memory", false, "Multi-memory")
+WABT_FEATURE(extended_const, "extended-const", false, "Extended constant expressions")
+WABT_FEATURE(relaxed_simd, "relaxed-simd", false, "Relaxed SIMD")
diff --git a/third_party/wasm2c/include/wabt/feature.h b/third_party/wasm2c/include/wabt/feature.h
new file mode 100644
index 0000000000..5a2886586b
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/feature.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_FEATURE_H_
+#define WABT_FEATURE_H_
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+class OptionParser;
+
+class Features {
+ public:
+ void AddOptions(OptionParser*);
+
+ void EnableAll() {
+#define WABT_FEATURE(variable, flag, default_, help) enable_##variable();
+#include "wabt/feature.def"
+#undef WABT_FEATURE
+ }
+
+#define WABT_FEATURE(variable, flag, default_, help) \
+ bool variable##_enabled() const { return variable##_enabled_; } \
+ void enable_##variable() { set_##variable##_enabled(true); } \
+ void disable_##variable() { set_##variable##_enabled(false); } \
+ void set_##variable##_enabled(bool value) { \
+ variable##_enabled_ = value; \
+ UpdateDependencies(); \
+ }
+#include "wabt/feature.def"
+#undef WABT_FEATURE
+
+ private:
+ void UpdateDependencies();
+
+#define WABT_FEATURE(variable, flag, default_, help) \
+ bool variable##_enabled_ = default_;
+#include "wabt/feature.def"
+#undef WABT_FEATURE
+};
+
+} // namespace wabt
+
+#endif // WABT_FEATURE_H_
diff --git a/third_party/wasm2c/include/wabt/filenames.h b/third_party/wasm2c/include/wabt/filenames.h
new file mode 100644
index 0000000000..983d2fbf52
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/filenames.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_FILENAMES_H_
+#define WABT_FILENAMES_H_
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+extern const char* kWasmExtension;
+extern const char* kWatExtension;
+
+// Return only the file extension, e.g.:
+//
+// "foo.txt", => ".txt"
+// "foo" => ""
+// "/foo/bar/foo.wasm" => ".wasm"
+std::string_view GetExtension(std::string_view filename);
+
+// Strip extension, e.g.:
+//
+// "foo", => "foo"
+// "foo.bar" => "foo"
+// "/path/to/foo.bar" => "/path/to/foo"
+// "\\path\\to\\foo.bar" => "\\path\\to\\foo"
+std::string_view StripExtension(std::string_view s);
+
+// Strip everything up to and including the last slash, e.g.:
+//
+// "/foo/bar/baz", => "baz"
+// "/usr/local/include/stdio.h", => "stdio.h"
+// "foo.bar", => "foo.bar"
+std::string_view GetBasename(std::string_view filename);
+
+} // namespace wabt
+
+#endif /* WABT_FILENAMES_H_ */
diff --git a/third_party/wasm2c/include/wabt/generate-names.h b/third_party/wasm2c/include/wabt/generate-names.h
new file mode 100644
index 0000000000..69dae8e20d
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/generate-names.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_GENERATE_NAMES_H_
+#define WABT_GENERATE_NAMES_H_
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+struct Module;
+
+enum NameOpts {
+ None = 0,
+ AlphaNames = 1 << 0,
+};
+
+Result GenerateNames(struct Module*, NameOpts opts = NameOpts::None);
+
+inline std::string IndexToAlphaName(Index index) {
+ std::string s;
+ do {
+ // For multiple chars, put most frequently changing char first.
+ s += 'a' + (index % 26);
+ index /= 26;
+ // Continue remaining sequence with 'a' rather than 'b'.
+ } while (index--);
+ return s;
+}
+
+} // namespace wabt
+
+#endif /* WABT_GENERATE_NAMES_H_ */
diff --git a/third_party/wasm2c/include/wabt/intrusive-list.h b/third_party/wasm2c/include/wabt/intrusive-list.h
new file mode 100644
index 0000000000..34332345a2
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/intrusive-list.h
@@ -0,0 +1,631 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_INTRUSIVE_LIST_H_
+#define WABT_INTRUSIVE_LIST_H_
+
+#include <cassert>
+#include <iterator>
+#include <memory>
+
+// This uses a similar interface as std::list, but is missing the following
+// features:
+//
+// * Add "extract_" functions that remove an element from the list and return
+// it.
+// * Only supports move-only operations
+// * No allocator support
+// * No initializer lists
+// * Asserts instead of exceptions
+// * Some functions are not implemented (merge, remove, remove_if, reverse,
+// unique, sort, non-member comparison operators)
+
+namespace wabt {
+
+template <typename T>
+class intrusive_list;
+
+template <typename T>
+class intrusive_list_base {
+ private:
+ friend class intrusive_list<T>;
+
+ mutable T* next_ = nullptr;
+ mutable T* prev_ = nullptr;
+};
+
+template <typename T>
+class intrusive_list {
+ public:
+ // types:
+ using value_type = T;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ class iterator;
+ class const_iterator;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ // construct/copy/destroy:
+ intrusive_list();
+ explicit intrusive_list(std::unique_ptr<T> node);
+ explicit intrusive_list(T&& node);
+ intrusive_list(const intrusive_list&) = delete;
+ intrusive_list(intrusive_list&&);
+ ~intrusive_list();
+ intrusive_list& operator=(const intrusive_list& other) = delete;
+ intrusive_list& operator=(intrusive_list&& other);
+
+ // iterators:
+ iterator begin() noexcept;
+ const_iterator begin() const noexcept;
+ iterator end() noexcept;
+ const_iterator end() const noexcept;
+
+ reverse_iterator rbegin() noexcept;
+ const_reverse_iterator rbegin() const noexcept;
+ reverse_iterator rend() noexcept;
+ const_reverse_iterator rend() const noexcept;
+
+ const_iterator cbegin() const noexcept;
+ const_iterator cend() const noexcept;
+ const_reverse_iterator crbegin() const noexcept;
+ const_reverse_iterator crend() const noexcept;
+
+ // capacity:
+ size_type size() const noexcept;
+ bool empty() const noexcept;
+
+ // element access:
+ reference front();
+ const_reference front() const;
+ reference back();
+ const_reference back() const;
+
+ // modifiers:
+ template <class... Args>
+ void emplace_front(Args&&... args);
+ template <class... Args>
+ void emplace_back(Args&&... args);
+ void push_front(std::unique_ptr<T> node);
+ void push_front(T&& node);
+ void push_back(std::unique_ptr<T> node);
+ void push_back(T&& node);
+ void pop_front();
+ void pop_back();
+ std::unique_ptr<T> extract_front();
+ std::unique_ptr<T> extract_back();
+
+ template <class... Args>
+ iterator emplace(iterator pos, Args&&... args);
+ iterator insert(iterator pos, std::unique_ptr<T> node);
+ iterator insert(iterator pos, T&& node);
+ std::unique_ptr<T> extract(iterator it);
+
+ iterator erase(iterator pos);
+ iterator erase(iterator first, iterator last);
+ void swap(intrusive_list&);
+ void clear() noexcept;
+
+ void splice(iterator pos, intrusive_list& node);
+ void splice(iterator pos, intrusive_list&& node);
+ void splice(iterator pos, intrusive_list& node, iterator it);
+ void splice(iterator pos,
+ intrusive_list& node,
+ iterator first,
+ iterator last);
+
+ private:
+ T* first_ = nullptr;
+ T* last_ = nullptr;
+ size_t size_ = 0;
+};
+
+/// iterator
+template <typename T>
+class intrusive_list<T>::iterator {
+ public:
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type = T;
+ using pointer = T*;
+ using reference = T&;
+
+ iterator(const intrusive_list<T>& list, T* node)
+ : list_(&list), node_(node) {}
+
+ reference operator*() const {
+ assert(node_);
+ return *node_;
+ }
+
+ pointer operator->() const {
+ assert(node_);
+ return node_;
+ }
+
+ iterator& operator++() {
+ assert(node_);
+ node_ = node_->next_;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ iterator tmp = *this;
+ operator++();
+ return tmp;
+ }
+
+ iterator& operator--() {
+ node_ = node_ ? node_->prev_ : list_->last_;
+ return *this;
+ }
+
+ iterator operator--(int) {
+ iterator tmp = *this;
+ operator--();
+ return tmp;
+ }
+
+ bool operator==(iterator rhs) const {
+ assert(list_ == rhs.list_);
+ return node_ == rhs.node_;
+ }
+
+ bool operator!=(iterator rhs) const {
+ assert(list_ == rhs.list_);
+ return node_ != rhs.node_;
+ }
+
+ private:
+ friend class const_iterator;
+
+ const intrusive_list<T>* list_;
+ T* node_;
+};
+
+/// const_iterator
+template <typename T>
+class intrusive_list<T>::const_iterator {
+ public:
+ using difference_type = std::ptrdiff_t;
+ using iterator_category = std::bidirectional_iterator_tag;
+ using value_type = T;
+ using pointer = const T*;
+ using reference = const T&;
+
+ const_iterator(const intrusive_list<T>& list, T* node)
+ : list_(&list), node_(node) {}
+
+ const_iterator(const iterator& other)
+ : list_(other.list_), node_(other.node_) {}
+
+ reference operator*() const {
+ assert(node_);
+ return *node_;
+ }
+
+ pointer operator->() const {
+ assert(node_);
+ return node_;
+ }
+
+ const_iterator& operator++() {
+ assert(node_);
+ node_ = node_->next_;
+ return *this;
+ }
+
+ const_iterator operator++(int) {
+ const_iterator tmp = *this;
+ operator++();
+ return tmp;
+ }
+
+ const_iterator& operator--() {
+ node_ = node_ ? node_->prev_ : list_->last_;
+ return *this;
+ }
+
+ const_iterator operator--(int) {
+ const_iterator tmp = *this;
+ operator--();
+ return tmp;
+ }
+
+ bool operator==(const_iterator rhs) const {
+ assert(list_ == rhs.list_);
+ return node_ == rhs.node_;
+ }
+
+ bool operator!=(const_iterator rhs) const {
+ assert(list_ == rhs.list_);
+ return node_ != rhs.node_;
+ }
+
+ private:
+ const intrusive_list<T>* list_;
+ T* node_;
+};
+
+template <typename T>
+inline intrusive_list<T>::intrusive_list() {}
+
+template <typename T>
+inline intrusive_list<T>::intrusive_list(std::unique_ptr<T> node) {
+ push_back(std::move(node));
+}
+
+template <typename T>
+inline intrusive_list<T>::intrusive_list(T&& node) {
+ push_back(std::move(node));
+}
+
+template <typename T>
+inline intrusive_list<T>::intrusive_list(intrusive_list&& other)
+ : first_(other.first_), last_(other.last_), size_(other.size_) {
+ other.first_ = other.last_ = nullptr;
+ other.size_ = 0;
+}
+
+template <typename T>
+inline intrusive_list<T>::~intrusive_list() {
+ clear();
+}
+
+template <typename T>
+inline intrusive_list<T>& intrusive_list<T>::operator=(
+ intrusive_list<T>&& other) {
+ clear();
+ first_ = other.first_;
+ last_ = other.last_;
+ size_ = other.size_;
+ other.first_ = other.last_ = nullptr;
+ other.size_ = 0;
+ return *this;
+}
+
+template <typename T>
+inline typename intrusive_list<T>::iterator
+intrusive_list<T>::begin() noexcept {
+ return iterator(*this, first_);
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_iterator intrusive_list<T>::begin()
+ const noexcept {
+ return const_iterator(*this, first_);
+}
+
+template <typename T>
+inline typename intrusive_list<T>::iterator intrusive_list<T>::end() noexcept {
+ return iterator(*this, nullptr);
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_iterator intrusive_list<T>::end()
+ const noexcept {
+ return const_iterator(*this, nullptr);
+}
+
+template <typename T>
+inline typename intrusive_list<T>::reverse_iterator
+intrusive_list<T>::rbegin() noexcept {
+ return reverse_iterator(iterator(*this, nullptr));
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reverse_iterator
+intrusive_list<T>::rbegin() const noexcept {
+ return const_reverse_iterator(const_iterator(*this, nullptr));
+}
+
+template <typename T>
+inline typename intrusive_list<T>::reverse_iterator
+intrusive_list<T>::rend() noexcept {
+ return reverse_iterator(iterator(*this, first_));
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reverse_iterator
+intrusive_list<T>::rend() const noexcept {
+ return const_reverse_iterator(const_iterator(*this, first_));
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_iterator intrusive_list<T>::cbegin()
+ const noexcept {
+ return const_iterator(*this, first_);
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_iterator intrusive_list<T>::cend()
+ const noexcept {
+ return const_iterator(*this, nullptr);
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reverse_iterator
+intrusive_list<T>::crbegin() const noexcept {
+ return const_reverse_iterator(const_iterator(*this, nullptr));
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reverse_iterator
+intrusive_list<T>::crend() const noexcept {
+ return const_reverse_iterator(const_iterator(*this, first_));
+}
+
+template <typename T>
+inline typename intrusive_list<T>::size_type intrusive_list<T>::size()
+ const noexcept {
+ return size_;
+}
+
+template <typename T>
+inline bool intrusive_list<T>::empty() const noexcept {
+ return size_ == 0;
+}
+
+template <typename T>
+inline typename intrusive_list<T>::reference intrusive_list<T>::front() {
+ assert(!empty());
+ return *first_;
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reference intrusive_list<T>::front()
+ const {
+ assert(!empty());
+ return *first_;
+}
+
+template <typename T>
+inline typename intrusive_list<T>::reference intrusive_list<T>::back() {
+ assert(!empty());
+ return *last_;
+}
+
+template <typename T>
+inline typename intrusive_list<T>::const_reference intrusive_list<T>::back()
+ const {
+ assert(!empty());
+ return *last_;
+}
+
+template <typename T>
+template <class... Args>
+inline void intrusive_list<T>::emplace_front(Args&&... args) {
+ push_front(std::make_unique<T>(std::forward<Args>(args)...));
+}
+
+template <typename T>
+template <class... Args>
+inline void intrusive_list<T>::emplace_back(Args&&... args) {
+ push_back(std::make_unique<T>(std::forward<Args>(args)...));
+}
+
+template <typename T>
+inline void intrusive_list<T>::push_front(std::unique_ptr<T> node) {
+ assert(node->prev_ == nullptr && node->next_ == nullptr);
+
+ T* node_p = node.release();
+ if (first_) {
+ node_p->next_ = first_;
+ first_->prev_ = node_p;
+ } else {
+ last_ = node_p;
+ }
+ first_ = node_p;
+ size_++;
+}
+
+template <typename T>
+inline void intrusive_list<T>::push_front(T&& node) {
+ push_front(std::make_unique<T>(std::move(node)));
+}
+
+template <typename T>
+inline void intrusive_list<T>::push_back(std::unique_ptr<T> node) {
+ assert(node->prev_ == nullptr && node->next_ == nullptr);
+
+ T* node_p = node.release();
+ if (last_) {
+ node_p->prev_ = last_;
+ last_->next_ = node_p;
+ } else {
+ first_ = node_p;
+ }
+ last_ = node_p;
+ size_++;
+}
+
+template <typename T>
+inline void intrusive_list<T>::push_back(T&& node) {
+ push_back(std::make_unique<T>(std::move(node)));
+}
+
+template <typename T>
+inline void intrusive_list<T>::pop_front() {
+ extract_front();
+}
+
+template <typename T>
+inline void intrusive_list<T>::pop_back() {
+ extract_back();
+}
+
+template <typename T>
+inline std::unique_ptr<T> intrusive_list<T>::extract_front() {
+ assert(!empty());
+ T* node = first_;
+ if (first_ == last_) {
+ first_ = last_ = nullptr;
+ } else {
+ first_ = first_->next_;
+ first_->prev_ = nullptr;
+ }
+ node->next_ = node->prev_ = nullptr;
+ size_--;
+ return std::unique_ptr<T>(node);
+}
+
+template <typename T>
+inline std::unique_ptr<T> intrusive_list<T>::extract_back() {
+ assert(!empty());
+ T* node = last_;
+ if (first_ == last_) {
+ first_ = last_ = nullptr;
+ } else {
+ last_ = last_->prev_;
+ last_->next_ = nullptr;
+ }
+ node->next_ = node->prev_ = nullptr;
+ size_--;
+ return std::unique_ptr<T>(node);
+}
+
+template <typename T>
+template <class... Args>
+inline typename intrusive_list<T>::iterator intrusive_list<T>::emplace(
+ iterator pos,
+ Args&&... args) {
+ return insert(pos, std::make_unique<T>(std::forward<Args>(args)...));
+}
+
+template <typename T>
+inline typename intrusive_list<T>::iterator intrusive_list<T>::insert(
+ iterator pos,
+ std::unique_ptr<T> node) {
+ assert(node->prev_ == nullptr && node->next_ == nullptr);
+
+ T* node_p;
+ if (pos == end()) {
+ push_back(std::move(node));
+ node_p = &back();
+ } else {
+ node_p = node.release();
+ node_p->prev_ = pos->prev_;
+ node_p->next_ = &*pos;
+ if (pos->prev_) {
+ pos->prev_->next_ = node_p;
+ } else {
+ first_ = node_p;
+ }
+ pos->prev_ = node_p;
+ size_++;
+ }
+ return iterator(*this, node_p);
+}
+
+template <typename T>
+inline typename intrusive_list<T>::iterator intrusive_list<T>::insert(
+ iterator pos,
+ T&& node) {
+ return insert(pos, std::make_unique<T>(std::move(node)));
+}
+
+template <typename T>
+inline std::unique_ptr<T> intrusive_list<T>::extract(iterator pos) {
+ assert(!empty());
+ assert(pos != end());
+ T* node = &*pos;
+ if (first_ == last_) {
+ first_ = last_ = nullptr;
+ } else {
+ if (node->prev_) {
+ node->prev_->next_ = node->next_;
+ } else {
+ first_ = node->next_;
+ }
+
+ if (node->next_) {
+ node->next_->prev_ = node->prev_;
+ } else {
+ last_ = node->prev_;
+ }
+ }
+ node->next_ = node->prev_ = nullptr;
+ size_--;
+ return std::unique_ptr<T>(node);
+}
+
+template <typename T>
+inline typename intrusive_list<T>::iterator intrusive_list<T>::erase(
+ iterator pos) {
+ iterator next = std::next(pos);
+ extract(pos);
+ return next;
+}
+
+template <typename T>
+inline typename intrusive_list<T>::iterator intrusive_list<T>::erase(
+ iterator first,
+ iterator last) {
+ while (first != last)
+ first = erase(first);
+ return first;
+}
+
+template <typename T>
+inline void intrusive_list<T>::swap(intrusive_list& other) {
+ std::swap(first_, other.first_);
+ std::swap(last_, other.last_);
+ std::swap(size_, other.size_);
+}
+
+template <typename T>
+inline void intrusive_list<T>::clear() noexcept {
+ for (T* iter = first_; iter;) {
+ T* next = iter->next_;
+ delete iter;
+ iter = next;
+ }
+ first_ = last_ = nullptr;
+ size_ = 0;
+}
+
+template <typename T>
+inline void intrusive_list<T>::splice(iterator pos, intrusive_list& other) {
+ splice(pos, other, other.begin(), other.end());
+}
+
+template <typename T>
+inline void intrusive_list<T>::splice(iterator pos, intrusive_list&& other) {
+ splice(pos, other, other.begin(), other.end());
+}
+
+template <typename T>
+inline void intrusive_list<T>::splice(iterator pos,
+ intrusive_list& other,
+ iterator it) {
+ insert(pos, other.extract(it));
+}
+
+template <typename T>
+inline void intrusive_list<T>::splice(iterator pos,
+ intrusive_list& other,
+ iterator first,
+ iterator last) {
+ while (first != last)
+ insert(pos, other.extract(first++));
+}
+
+} // namespace wabt
+
+#endif // WABT_INTRUSIVE_LIST_H_
diff --git a/third_party/wasm2c/include/wabt/ir-util.h b/third_party/wasm2c/include/wabt/ir-util.h
new file mode 100644
index 0000000000..7d06121902
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/ir-util.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_IR_UTIL_H_
+#define WABT_IR_UTIL_H_
+
+#include "wabt/common.h"
+#include "wabt/ir.h"
+
+namespace wabt {
+
+struct Label {
+ Label(LabelType label_type,
+ const std::string& name,
+ const TypeVector& param_types,
+ const TypeVector& result_types)
+ : name(name),
+ label_type(label_type),
+ param_types(param_types),
+ result_types(result_types) {}
+
+ std::string name;
+ LabelType label_type;
+ TypeVector param_types;
+ TypeVector result_types;
+};
+
+struct ModuleContext {
+ ModuleContext(const Module& module) : module(module) {}
+
+ Index GetLabelStackSize() const { return label_stack_.size(); }
+ const Label* GetLabel(const Var& var) const;
+ Index GetLabelArity(const Var& var) const;
+ void SetTopLabelType(LabelType label_type) {
+ label_stack_.back().label_type = label_type;
+ }
+
+ Index GetFuncParamCount(const Var& var) const;
+ Index GetFuncResultCount(const Var& var) const;
+
+ void BeginBlock(LabelType label_type, const Block& block);
+ void EndBlock();
+ void BeginFunc(const Func& func);
+ void EndFunc();
+
+ struct Arities {
+ Index nargs;
+ Index nreturns;
+ bool unreachable;
+ Arities(Index na, Index nr, bool ur = false)
+ : nargs(na), nreturns(nr), unreachable(ur) {}
+ };
+ Arities GetExprArity(const Expr& expr) const;
+
+ const Module& module;
+
+ private:
+ const Func* current_func_ = nullptr;
+ std::vector<Label> label_stack_;
+};
+
+} // namespace wabt
+
+#endif /* WABT_IR_UTIL_H_ */
diff --git a/third_party/wasm2c/include/wabt/ir.h b/third_party/wasm2c/include/wabt/ir.h
new file mode 100644
index 0000000000..68846bc0cc
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/ir.h
@@ -0,0 +1,1483 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_IR_H_
+#define WABT_IR_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <type_traits>
+#include <vector>
+
+#include "wabt/binding-hash.h"
+#include "wabt/common.h"
+#include "wabt/intrusive-list.h"
+#include "wabt/opcode.h"
+
+namespace wabt {
+
+struct Module;
+
+enum class VarType {
+ Index,
+ Name,
+};
+
+struct Var {
+ explicit Var();
+ explicit Var(Index index, const Location& loc);
+ explicit Var(std::string_view name, const Location& loc);
+ Var(Var&&);
+ Var(const Var&);
+ Var& operator=(const Var&);
+ Var& operator=(Var&&);
+ ~Var();
+
+ VarType type() const { return type_; }
+ bool is_index() const { return type_ == VarType::Index; }
+ bool is_name() const { return type_ == VarType::Name; }
+
+ Index index() const {
+ assert(is_index());
+ return index_;
+ }
+ const std::string& name() const {
+ assert(is_name());
+ return name_;
+ }
+
+ void set_index(Index);
+ void set_name(std::string&&);
+ void set_name(std::string_view);
+
+ Location loc;
+
+ private:
+ void Destroy();
+
+ VarType type_;
+ union {
+ Index index_;
+ std::string name_;
+ };
+};
+using VarVector = std::vector<Var>;
+
+struct Const {
+ static constexpr uintptr_t kRefNullBits = ~uintptr_t(0);
+
+ Const() : Const(Type::I32, uint32_t(0)) {}
+
+ static Const I32(uint32_t val = 0, const Location& loc = Location()) {
+ return Const(Type::I32, val, loc);
+ }
+ static Const I64(uint64_t val = 0, const Location& loc = Location()) {
+ return Const(Type::I64, val, loc);
+ }
+ static Const F32(uint32_t val = 0, const Location& loc = Location()) {
+ return Const(Type::F32, val, loc);
+ }
+ static Const F64(uint64_t val = 0, const Location& loc = Location()) {
+ return Const(Type::F64, val, loc);
+ }
+ static Const V128(v128 val, const Location& loc = Location()) {
+ return Const(Type::V128, val, loc);
+ }
+
+ Type type() const { return type_; }
+ Type lane_type() const {
+ assert(type_ == Type::V128);
+ return lane_type_;
+ }
+
+ int lane_count() const {
+ switch (lane_type()) {
+ case Type::I8: return 16;
+ case Type::I16: return 8;
+ case Type::I32: return 4;
+ case Type::I64: return 2;
+ case Type::F32: return 4;
+ case Type::F64: return 2;
+ default: WABT_UNREACHABLE;
+ }
+ }
+
+ uint32_t u32() const { return data_.u32(0); }
+ uint64_t u64() const { return data_.u64(0); }
+ uint32_t f32_bits() const { return data_.f32_bits(0); }
+ uint64_t f64_bits() const { return data_.f64_bits(0); }
+ uintptr_t ref_bits() const { return data_.To<uintptr_t>(0); }
+ v128 vec128() const { return data_; }
+
+ template <typename T>
+ T v128_lane(int lane) const {
+ return data_.To<T>(lane);
+ }
+
+ void set_u32(uint32_t x) { From(Type::I32, x); }
+ void set_u64(uint64_t x) { From(Type::I64, x); }
+ void set_f32(uint32_t x) { From(Type::F32, x); }
+ void set_f64(uint64_t x) { From(Type::F64, x); }
+
+ void set_v128_u8(int lane, uint8_t x) { set_v128_lane(lane, Type::I8, x); }
+ void set_v128_u16(int lane, uint16_t x) { set_v128_lane(lane, Type::I16, x); }
+ void set_v128_u32(int lane, uint32_t x) { set_v128_lane(lane, Type::I32, x); }
+ void set_v128_u64(int lane, uint64_t x) { set_v128_lane(lane, Type::I64, x); }
+ void set_v128_f32(int lane, uint32_t x) { set_v128_lane(lane, Type::F32, x); }
+ void set_v128_f64(int lane, uint64_t x) { set_v128_lane(lane, Type::F64, x); }
+
+ // Only used for expectations. (e.g. wast assertions)
+ void set_f32(ExpectedNan nan) {
+ set_f32(0);
+ set_expected_nan(0, nan);
+ }
+ void set_f64(ExpectedNan nan) {
+ set_f64(0);
+ set_expected_nan(0, nan);
+ }
+ void set_funcref() { From<uintptr_t>(Type::FuncRef, 0); }
+ void set_externref(uintptr_t x) { From(Type::ExternRef, x); }
+ void set_null(Type type) { From<uintptr_t>(type, kRefNullBits); }
+
+ bool is_expected_nan(int lane = 0) const {
+ return expected_nan(lane) != ExpectedNan::None;
+ }
+
+ ExpectedNan expected_nan(int lane = 0) const {
+ return lane < 4 ? nan_[lane] : ExpectedNan::None;
+ }
+
+ void set_expected_nan(int lane, ExpectedNan nan) {
+ if (lane < 4) {
+ nan_[lane] = nan;
+ }
+ }
+
+ // v128 support
+ Location loc;
+
+ private:
+ template <typename T>
+ void set_v128_lane(int lane, Type lane_type, T x) {
+ lane_type_ = lane_type;
+ From(Type::V128, x, lane);
+ set_expected_nan(lane, ExpectedNan::None);
+ }
+
+ template <typename T>
+ Const(Type type, T data, const Location& loc = Location()) : loc(loc) {
+ From<T>(type, data);
+ }
+
+ template <typename T>
+ void From(Type type, T data, int lane = 0) {
+ static_assert(sizeof(T) <= sizeof(data_), "Invalid cast!");
+ assert((lane + 1) * sizeof(T) <= sizeof(data_));
+ type_ = type;
+ data_.From<T>(lane, data);
+ set_expected_nan(lane, ExpectedNan::None);
+ }
+
+ Type type_;
+ Type lane_type_; // Only valid if type_ == Type::V128.
+ v128 data_;
+ ExpectedNan nan_[4];
+};
+using ConstVector = std::vector<Const>;
+
+enum class ExpectationType {
+ Values,
+ Either,
+};
+
+class Expectation {
+ public:
+ Expectation() = delete;
+ virtual ~Expectation() = default;
+ ExpectationType type() const { return type_; }
+
+ Location loc;
+
+ ConstVector expected;
+
+ protected:
+ explicit Expectation(ExpectationType type, const Location& loc = Location())
+ : loc(loc), type_(type) {}
+
+ private:
+ ExpectationType type_;
+};
+
+template <ExpectationType TypeEnum>
+class ExpectationMixin : public Expectation {
+ public:
+ static bool classof(const Expectation* expectation) {
+ return expectation->type() == TypeEnum;
+ }
+
+ explicit ExpectationMixin(const Location& loc = Location())
+ : Expectation(TypeEnum, loc) {}
+};
+
+class ValueExpectation : public ExpectationMixin<ExpectationType::Values> {
+ public:
+ explicit ValueExpectation(const Location& loc = Location())
+ : ExpectationMixin<ExpectationType::Values>(loc) {}
+};
+
+struct EitherExpectation : public ExpectationMixin<ExpectationType::Either> {
+ public:
+ explicit EitherExpectation(const Location& loc = Location())
+ : ExpectationMixin<ExpectationType::Either>(loc) {}
+};
+
+typedef std::unique_ptr<Expectation> ExpectationPtr;
+
+struct FuncSignature {
+ TypeVector param_types;
+ TypeVector result_types;
+
+ // Some types can have names, for example (ref $foo) has type $foo.
+ // So to use this type we need to translate its name into
+ // a proper index from the module type section.
+ // This is the mapping from parameter/result index to its name.
+ std::unordered_map<uint32_t, std::string> param_type_names;
+ std::unordered_map<uint32_t, std::string> result_type_names;
+
+ Index GetNumParams() const { return param_types.size(); }
+ Index GetNumResults() const { return result_types.size(); }
+ Type GetParamType(Index index) const { return param_types[index]; }
+ Type GetResultType(Index index) const { return result_types[index]; }
+
+ bool operator==(const FuncSignature&) const;
+};
+
+enum class TypeEntryKind {
+ Func,
+ Struct,
+ Array,
+};
+
+class TypeEntry {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(TypeEntry);
+
+ virtual ~TypeEntry() = default;
+
+ TypeEntryKind kind() const { return kind_; }
+
+ Location loc;
+ std::string name;
+
+ protected:
+ explicit TypeEntry(TypeEntryKind kind,
+ std::string_view name = std::string_view(),
+ const Location& loc = Location())
+ : loc(loc), name(name), kind_(kind) {}
+
+ TypeEntryKind kind_;
+};
+
+class FuncType : public TypeEntry {
+ public:
+ static bool classof(const TypeEntry* entry) {
+ return entry->kind() == TypeEntryKind::Func;
+ }
+
+ explicit FuncType(std::string_view name = std::string_view())
+ : TypeEntry(TypeEntryKind::Func, name) {}
+
+ Index GetNumParams() const { return sig.GetNumParams(); }
+ Index GetNumResults() const { return sig.GetNumResults(); }
+ Type GetParamType(Index index) const { return sig.GetParamType(index); }
+ Type GetResultType(Index index) const { return sig.GetResultType(index); }
+
+ FuncSignature sig;
+};
+
+struct Field {
+ std::string name;
+ Type type = Type::Void;
+ bool mutable_ = false;
+};
+
+class StructType : public TypeEntry {
+ public:
+ static bool classof(const TypeEntry* entry) {
+ return entry->kind() == TypeEntryKind::Struct;
+ }
+
+ explicit StructType(std::string_view name = std::string_view())
+ : TypeEntry(TypeEntryKind::Struct) {}
+
+ std::vector<Field> fields;
+};
+
+class ArrayType : public TypeEntry {
+ public:
+ static bool classof(const TypeEntry* entry) {
+ return entry->kind() == TypeEntryKind::Array;
+ }
+
+ explicit ArrayType(std::string_view name = std::string_view())
+ : TypeEntry(TypeEntryKind::Array) {}
+
+ Field field;
+};
+
+struct FuncDeclaration {
+ Index GetNumParams() const { return sig.GetNumParams(); }
+ Index GetNumResults() const { return sig.GetNumResults(); }
+ Type GetParamType(Index index) const { return sig.GetParamType(index); }
+ Type GetResultType(Index index) const { return sig.GetResultType(index); }
+
+ bool has_func_type = false;
+ Var type_var;
+ FuncSignature sig;
+};
+
+enum class ExprType {
+ AtomicLoad,
+ AtomicRmw,
+ AtomicRmwCmpxchg,
+ AtomicStore,
+ AtomicNotify,
+ AtomicFence,
+ AtomicWait,
+ Binary,
+ Block,
+ Br,
+ BrIf,
+ BrTable,
+ Call,
+ CallIndirect,
+ CallRef,
+ CodeMetadata,
+ Compare,
+ Const,
+ Convert,
+ Drop,
+ GlobalGet,
+ GlobalSet,
+ If,
+ Load,
+ LocalGet,
+ LocalSet,
+ LocalTee,
+ Loop,
+ MemoryCopy,
+ DataDrop,
+ MemoryFill,
+ MemoryGrow,
+ MemoryInit,
+ MemorySize,
+ Nop,
+ RefIsNull,
+ RefFunc,
+ RefNull,
+ Rethrow,
+ Return,
+ ReturnCall,
+ ReturnCallIndirect,
+ Select,
+ SimdLaneOp,
+ SimdLoadLane,
+ SimdStoreLane,
+ SimdShuffleOp,
+ LoadSplat,
+ LoadZero,
+ Store,
+ TableCopy,
+ ElemDrop,
+ TableInit,
+ TableGet,
+ TableGrow,
+ TableSize,
+ TableSet,
+ TableFill,
+ Ternary,
+ Throw,
+ Try,
+ Unary,
+ Unreachable,
+
+ First = AtomicLoad,
+ Last = Unreachable
+};
+
+const char* GetExprTypeName(ExprType type);
+
+class Expr;
+using ExprList = intrusive_list<Expr>;
+
+using BlockDeclaration = FuncDeclaration;
+
+struct Block {
+ Block() = default;
+ explicit Block(ExprList exprs) : exprs(std::move(exprs)) {}
+
+ std::string label;
+ BlockDeclaration decl;
+ ExprList exprs;
+ Location end_loc;
+};
+
+struct Catch {
+ explicit Catch(const Location& loc = Location()) : loc(loc) {}
+ explicit Catch(const Var& var, const Location& loc = Location())
+ : loc(loc), var(var) {}
+ Location loc;
+ Var var;
+ ExprList exprs;
+ bool IsCatchAll() const {
+ return var.is_index() && var.index() == kInvalidIndex;
+ }
+};
+using CatchVector = std::vector<Catch>;
+
+enum class TryKind { Plain, Catch, Delegate };
+
+class Expr : public intrusive_list_base<Expr> {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(Expr);
+ Expr() = delete;
+ virtual ~Expr() = default;
+
+ ExprType type() const { return type_; }
+
+ Location loc;
+
+ protected:
+ explicit Expr(ExprType type, const Location& loc = Location())
+ : loc(loc), type_(type) {}
+
+ ExprType type_;
+};
+
+const char* GetExprTypeName(const Expr& expr);
+
+template <ExprType TypeEnum>
+class ExprMixin : public Expr {
+ public:
+ static bool classof(const Expr* expr) { return expr->type() == TypeEnum; }
+
+ explicit ExprMixin(const Location& loc = Location()) : Expr(TypeEnum, loc) {}
+};
+
+template <ExprType TypeEnum>
+class MemoryExpr : public ExprMixin<TypeEnum> {
+ public:
+ MemoryExpr(Var memidx, const Location& loc = Location())
+ : ExprMixin<TypeEnum>(loc), memidx(memidx) {}
+
+ Var memidx;
+};
+
+template <ExprType TypeEnum>
+class MemoryBinaryExpr : public ExprMixin<TypeEnum> {
+ public:
+ MemoryBinaryExpr(Var srcmemidx,
+ Var destmemidx,
+ const Location& loc = Location())
+ : ExprMixin<TypeEnum>(loc),
+ srcmemidx(srcmemidx),
+ destmemidx(destmemidx) {}
+
+ Var srcmemidx;
+ Var destmemidx;
+};
+
+using DropExpr = ExprMixin<ExprType::Drop>;
+using NopExpr = ExprMixin<ExprType::Nop>;
+using ReturnExpr = ExprMixin<ExprType::Return>;
+using UnreachableExpr = ExprMixin<ExprType::Unreachable>;
+
+using MemoryGrowExpr = MemoryExpr<ExprType::MemoryGrow>;
+using MemorySizeExpr = MemoryExpr<ExprType::MemorySize>;
+using MemoryFillExpr = MemoryExpr<ExprType::MemoryFill>;
+
+using MemoryCopyExpr = MemoryBinaryExpr<ExprType::MemoryCopy>;
+
+template <ExprType TypeEnum>
+class RefTypeExpr : public ExprMixin<TypeEnum> {
+ public:
+ RefTypeExpr(Type type, const Location& loc = Location())
+ : ExprMixin<TypeEnum>(loc), type(type) {}
+
+ Type type;
+};
+
+using RefNullExpr = RefTypeExpr<ExprType::RefNull>;
+using RefIsNullExpr = ExprMixin<ExprType::RefIsNull>;
+
+template <ExprType TypeEnum>
+class OpcodeExpr : public ExprMixin<TypeEnum> {
+ public:
+ OpcodeExpr(Opcode opcode, const Location& loc = Location())
+ : ExprMixin<TypeEnum>(loc), opcode(opcode) {}
+
+ Opcode opcode;
+};
+
+using BinaryExpr = OpcodeExpr<ExprType::Binary>;
+using CompareExpr = OpcodeExpr<ExprType::Compare>;
+using ConvertExpr = OpcodeExpr<ExprType::Convert>;
+using UnaryExpr = OpcodeExpr<ExprType::Unary>;
+using TernaryExpr = OpcodeExpr<ExprType::Ternary>;
+
+class SimdLaneOpExpr : public ExprMixin<ExprType::SimdLaneOp> {
+ public:
+ SimdLaneOpExpr(Opcode opcode, uint64_t val, const Location& loc = Location())
+ : ExprMixin<ExprType::SimdLaneOp>(loc), opcode(opcode), val(val) {}
+
+ Opcode opcode;
+ uint64_t val;
+};
+
+class SimdLoadLaneExpr : public MemoryExpr<ExprType::SimdLoadLane> {
+ public:
+ SimdLoadLaneExpr(Opcode opcode,
+ Var memidx,
+ Address align,
+ Address offset,
+ uint64_t val,
+ const Location& loc = Location())
+ : MemoryExpr<ExprType::SimdLoadLane>(memidx, loc),
+ opcode(opcode),
+ align(align),
+ offset(offset),
+ val(val) {}
+
+ Opcode opcode;
+ Address align;
+ Address offset;
+ uint64_t val;
+};
+
+class SimdStoreLaneExpr : public MemoryExpr<ExprType::SimdStoreLane> {
+ public:
+ SimdStoreLaneExpr(Opcode opcode,
+ Var memidx,
+ Address align,
+ Address offset,
+ uint64_t val,
+ const Location& loc = Location())
+ : MemoryExpr<ExprType::SimdStoreLane>(memidx, loc),
+ opcode(opcode),
+ align(align),
+ offset(offset),
+ val(val) {}
+
+ Opcode opcode;
+ Address align;
+ Address offset;
+ uint64_t val;
+};
+
+class SimdShuffleOpExpr : public ExprMixin<ExprType::SimdShuffleOp> {
+ public:
+ SimdShuffleOpExpr(Opcode opcode, v128 val, const Location& loc = Location())
+ : ExprMixin<ExprType::SimdShuffleOp>(loc), opcode(opcode), val(val) {}
+
+ Opcode opcode;
+ v128 val;
+};
+
+template <ExprType TypeEnum>
+class VarExpr : public ExprMixin<TypeEnum> {
+ public:
+ VarExpr(const Var& var, const Location& loc = Location())
+ : ExprMixin<TypeEnum>(loc), var(var) {}
+
+ Var var;
+};
+
+template <ExprType TypeEnum>
+class MemoryVarExpr : public MemoryExpr<TypeEnum> {
+ public:
+ MemoryVarExpr(const Var& var, Var memidx, const Location& loc = Location())
+ : MemoryExpr<TypeEnum>(memidx, loc), var(var) {}
+
+ Var var;
+};
+
+using BrExpr = VarExpr<ExprType::Br>;
+using BrIfExpr = VarExpr<ExprType::BrIf>;
+using CallExpr = VarExpr<ExprType::Call>;
+using RefFuncExpr = VarExpr<ExprType::RefFunc>;
+using GlobalGetExpr = VarExpr<ExprType::GlobalGet>;
+using GlobalSetExpr = VarExpr<ExprType::GlobalSet>;
+using LocalGetExpr = VarExpr<ExprType::LocalGet>;
+using LocalSetExpr = VarExpr<ExprType::LocalSet>;
+using LocalTeeExpr = VarExpr<ExprType::LocalTee>;
+using ReturnCallExpr = VarExpr<ExprType::ReturnCall>;
+using ThrowExpr = VarExpr<ExprType::Throw>;
+using RethrowExpr = VarExpr<ExprType::Rethrow>;
+
+using DataDropExpr = VarExpr<ExprType::DataDrop>;
+using ElemDropExpr = VarExpr<ExprType::ElemDrop>;
+using TableGetExpr = VarExpr<ExprType::TableGet>;
+using TableSetExpr = VarExpr<ExprType::TableSet>;
+using TableGrowExpr = VarExpr<ExprType::TableGrow>;
+using TableSizeExpr = VarExpr<ExprType::TableSize>;
+using TableFillExpr = VarExpr<ExprType::TableFill>;
+
+using MemoryInitExpr = MemoryVarExpr<ExprType::MemoryInit>;
+
+class SelectExpr : public ExprMixin<ExprType::Select> {
+ public:
+ SelectExpr(TypeVector type, const Location& loc = Location())
+ : ExprMixin<ExprType::Select>(loc), result_type(type) {}
+ TypeVector result_type;
+};
+
+class TableInitExpr : public ExprMixin<ExprType::TableInit> {
+ public:
+ TableInitExpr(const Var& segment_index,
+ const Var& table_index,
+ const Location& loc = Location())
+ : ExprMixin<ExprType::TableInit>(loc),
+ segment_index(segment_index),
+ table_index(table_index) {}
+
+ Var segment_index;
+ Var table_index;
+};
+
+class TableCopyExpr : public ExprMixin<ExprType::TableCopy> {
+ public:
+ TableCopyExpr(const Var& dst,
+ const Var& src,
+ const Location& loc = Location())
+ : ExprMixin<ExprType::TableCopy>(loc), dst_table(dst), src_table(src) {}
+
+ Var dst_table;
+ Var src_table;
+};
+
+class CallIndirectExpr : public ExprMixin<ExprType::CallIndirect> {
+ public:
+ explicit CallIndirectExpr(const Location& loc = Location())
+ : ExprMixin<ExprType::CallIndirect>(loc) {}
+
+ FuncDeclaration decl;
+ Var table;
+};
+
+class CodeMetadataExpr : public ExprMixin<ExprType::CodeMetadata> {
+ public:
+ explicit CodeMetadataExpr(std::string_view name,
+ std::vector<uint8_t> data,
+ const Location& loc = Location())
+ : ExprMixin<ExprType::CodeMetadata>(loc),
+ name(std::move(name)),
+ data(std::move(data)) {}
+
+ std::string_view name;
+ std::vector<uint8_t> data;
+};
+
+class ReturnCallIndirectExpr : public ExprMixin<ExprType::ReturnCallIndirect> {
+ public:
+ explicit ReturnCallIndirectExpr(const Location& loc = Location())
+ : ExprMixin<ExprType::ReturnCallIndirect>(loc) {}
+
+ FuncDeclaration decl;
+ Var table;
+};
+
+class CallRefExpr : public ExprMixin<ExprType::CallRef> {
+ public:
+ explicit CallRefExpr(const Location& loc = Location())
+ : ExprMixin<ExprType::CallRef>(loc) {}
+
+ // This field is setup only during Validate phase,
+ // so keep that in mind when you use it.
+ Var function_type_index;
+};
+
+template <ExprType TypeEnum>
+class BlockExprBase : public ExprMixin<TypeEnum> {
+ public:
+ explicit BlockExprBase(const Location& loc = Location())
+ : ExprMixin<TypeEnum>(loc) {}
+
+ Block block;
+};
+
+using BlockExpr = BlockExprBase<ExprType::Block>;
+using LoopExpr = BlockExprBase<ExprType::Loop>;
+
+class IfExpr : public ExprMixin<ExprType::If> {
+ public:
+ explicit IfExpr(const Location& loc = Location())
+ : ExprMixin<ExprType::If>(loc) {}
+
+ Block true_;
+ ExprList false_;
+ Location false_end_loc;
+};
+
+class TryExpr : public ExprMixin<ExprType::Try> {
+ public:
+ explicit TryExpr(const Location& loc = Location())
+ : ExprMixin<ExprType::Try>(loc), kind(TryKind::Plain) {}
+
+ TryKind kind;
+ Block block;
+ CatchVector catches;
+ Var delegate_target;
+};
+
+class BrTableExpr : public ExprMixin<ExprType::BrTable> {
+ public:
+ BrTableExpr(const Location& loc = Location())
+ : ExprMixin<ExprType::BrTable>(loc) {}
+
+ VarVector targets;
+ Var default_target;
+};
+
+class ConstExpr : public ExprMixin<ExprType::Const> {
+ public:
+ ConstExpr(const Const& c, const Location& loc = Location())
+ : ExprMixin<ExprType::Const>(loc), const_(c) {}
+
+ Const const_;
+};
+
+// TODO(binji): Rename this, it is used for more than loads/stores now.
+template <ExprType TypeEnum>
+class LoadStoreExpr : public MemoryExpr<TypeEnum> {
+ public:
+ LoadStoreExpr(Opcode opcode,
+ Var memidx,
+ Address align,
+ Address offset,
+ const Location& loc = Location())
+ : MemoryExpr<TypeEnum>(memidx, loc),
+ opcode(opcode),
+ align(align),
+ offset(offset) {}
+
+ Opcode opcode;
+ Address align;
+ Address offset;
+};
+
+using LoadExpr = LoadStoreExpr<ExprType::Load>;
+using StoreExpr = LoadStoreExpr<ExprType::Store>;
+
+using AtomicLoadExpr = LoadStoreExpr<ExprType::AtomicLoad>;
+using AtomicStoreExpr = LoadStoreExpr<ExprType::AtomicStore>;
+using AtomicRmwExpr = LoadStoreExpr<ExprType::AtomicRmw>;
+using AtomicRmwCmpxchgExpr = LoadStoreExpr<ExprType::AtomicRmwCmpxchg>;
+using AtomicWaitExpr = LoadStoreExpr<ExprType::AtomicWait>;
+using AtomicNotifyExpr = LoadStoreExpr<ExprType::AtomicNotify>;
+using LoadSplatExpr = LoadStoreExpr<ExprType::LoadSplat>;
+using LoadZeroExpr = LoadStoreExpr<ExprType::LoadZero>;
+
+class AtomicFenceExpr : public ExprMixin<ExprType::AtomicFence> {
+ public:
+ explicit AtomicFenceExpr(uint32_t consistency_model,
+ const Location& loc = Location())
+ : ExprMixin<ExprType::AtomicFence>(loc),
+ consistency_model(consistency_model) {}
+
+ uint32_t consistency_model;
+};
+
+struct Tag {
+ explicit Tag(std::string_view name) : name(name) {}
+
+ std::string name;
+ FuncDeclaration decl;
+};
+
+class LocalTypes {
+ public:
+ using Decl = std::pair<Type, Index>;
+ using Decls = std::vector<Decl>;
+
+ struct const_iterator {
+ const_iterator(Decls::const_iterator decl, Index index)
+ : decl(decl), index(index) {}
+ Type operator*() const { return decl->first; }
+ const_iterator& operator++();
+ const_iterator operator++(int);
+
+ Decls::const_iterator decl;
+ Index index;
+ };
+
+ void Set(const TypeVector&);
+
+ const Decls& decls() const { return decls_; }
+
+ void AppendDecl(Type type, Index count) {
+ if (count != 0) {
+ decls_.emplace_back(type, count);
+ }
+ }
+
+ Index size() const;
+ Type operator[](Index) const;
+
+ const_iterator begin() const { return {decls_.begin(), 0}; }
+ const_iterator end() const { return {decls_.end(), 0}; }
+
+ private:
+ Decls decls_;
+};
+
+inline LocalTypes::const_iterator& LocalTypes::const_iterator::operator++() {
+ ++index;
+ if (index >= decl->second) {
+ ++decl;
+ index = 0;
+ }
+ return *this;
+}
+
+inline LocalTypes::const_iterator LocalTypes::const_iterator::operator++(int) {
+ const_iterator result = *this;
+ operator++();
+ return result;
+}
+
+inline bool operator==(const LocalTypes::const_iterator& lhs,
+ const LocalTypes::const_iterator& rhs) {
+ return lhs.decl == rhs.decl && lhs.index == rhs.index;
+}
+
+inline bool operator!=(const LocalTypes::const_iterator& lhs,
+ const LocalTypes::const_iterator& rhs) {
+ return !operator==(lhs, rhs);
+}
+
+struct Func {
+ explicit Func(std::string_view name) : name(name) {}
+
+ Type GetParamType(Index index) const { return decl.GetParamType(index); }
+ Type GetResultType(Index index) const { return decl.GetResultType(index); }
+ Type GetLocalType(Index index) const;
+ Type GetLocalType(const Var& var) const;
+ Index GetNumParams() const { return decl.GetNumParams(); }
+ Index GetNumLocals() const { return local_types.size(); }
+ Index GetNumParamsAndLocals() const {
+ return GetNumParams() + GetNumLocals();
+ }
+ Index GetNumResults() const { return decl.GetNumResults(); }
+ Index GetLocalIndex(const Var&) const;
+
+ std::string name;
+ FuncDeclaration decl;
+ LocalTypes local_types;
+ BindingHash bindings;
+ ExprList exprs;
+ Location loc;
+};
+
+struct Global {
+ explicit Global(std::string_view name) : name(name) {}
+
+ std::string name;
+ Type type = Type::Void;
+ bool mutable_ = false;
+ ExprList init_expr;
+};
+
+struct Table {
+ explicit Table(std::string_view name)
+ : name(name), elem_type(Type::FuncRef) {}
+
+ std::string name;
+ Limits elem_limits;
+ Type elem_type;
+};
+
+using ExprListVector = std::vector<ExprList>;
+
+struct ElemSegment {
+ explicit ElemSegment(std::string_view name) : name(name) {}
+ uint8_t GetFlags(const Module*) const;
+
+ SegmentKind kind = SegmentKind::Active;
+ std::string name;
+ Var table_var;
+ Type elem_type;
+ ExprList offset;
+ ExprListVector elem_exprs;
+};
+
+struct Memory {
+ explicit Memory(std::string_view name) : name(name) {}
+
+ std::string name;
+ Limits page_limits;
+};
+
+struct DataSegment {
+ explicit DataSegment(std::string_view name) : name(name) {}
+ uint8_t GetFlags(const Module*) const;
+
+ SegmentKind kind = SegmentKind::Active;
+ std::string name;
+ Var memory_var;
+ ExprList offset;
+ std::vector<uint8_t> data;
+};
+
+class Import {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(Import);
+ Import() = delete;
+ virtual ~Import() = default;
+
+ ExternalKind kind() const { return kind_; }
+
+ std::string module_name;
+ std::string field_name;
+
+ protected:
+ Import(ExternalKind kind) : kind_(kind) {}
+
+ ExternalKind kind_;
+};
+
+template <ExternalKind TypeEnum>
+class ImportMixin : public Import {
+ public:
+ static bool classof(const Import* import) {
+ return import->kind() == TypeEnum;
+ }
+
+ ImportMixin() : Import(TypeEnum) {}
+};
+
+class FuncImport : public ImportMixin<ExternalKind::Func> {
+ public:
+ explicit FuncImport(std::string_view name = std::string_view())
+ : ImportMixin<ExternalKind::Func>(), func(name) {}
+
+ Func func;
+};
+
+class TableImport : public ImportMixin<ExternalKind::Table> {
+ public:
+ explicit TableImport(std::string_view name = std::string_view())
+ : ImportMixin<ExternalKind::Table>(), table(name) {}
+
+ Table table;
+};
+
+class MemoryImport : public ImportMixin<ExternalKind::Memory> {
+ public:
+ explicit MemoryImport(std::string_view name = std::string_view())
+ : ImportMixin<ExternalKind::Memory>(), memory(name) {}
+
+ Memory memory;
+};
+
+class GlobalImport : public ImportMixin<ExternalKind::Global> {
+ public:
+ explicit GlobalImport(std::string_view name = std::string_view())
+ : ImportMixin<ExternalKind::Global>(), global(name) {}
+
+ Global global;
+};
+
+class TagImport : public ImportMixin<ExternalKind::Tag> {
+ public:
+ explicit TagImport(std::string_view name = std::string_view())
+ : ImportMixin<ExternalKind::Tag>(), tag(name) {}
+
+ Tag tag;
+};
+
+struct Export {
+ std::string name;
+ ExternalKind kind;
+ Var var;
+};
+
+enum class ModuleFieldType {
+ Func,
+ Global,
+ Import,
+ Export,
+ Type,
+ Table,
+ ElemSegment,
+ Memory,
+ DataSegment,
+ Start,
+ Tag
+};
+
+class ModuleField : public intrusive_list_base<ModuleField> {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(ModuleField);
+ ModuleField() = delete;
+ virtual ~ModuleField() = default;
+
+ ModuleFieldType type() const { return type_; }
+
+ Location loc;
+
+ protected:
+ ModuleField(ModuleFieldType type, const Location& loc)
+ : loc(loc), type_(type) {}
+
+ ModuleFieldType type_;
+};
+
+using ModuleFieldList = intrusive_list<ModuleField>;
+
+template <ModuleFieldType TypeEnum>
+class ModuleFieldMixin : public ModuleField {
+ public:
+ static bool classof(const ModuleField* field) {
+ return field->type() == TypeEnum;
+ }
+
+ explicit ModuleFieldMixin(const Location& loc) : ModuleField(TypeEnum, loc) {}
+};
+
+class FuncModuleField : public ModuleFieldMixin<ModuleFieldType::Func> {
+ public:
+ explicit FuncModuleField(const Location& loc = Location(),
+ std::string_view name = std::string_view())
+ : ModuleFieldMixin<ModuleFieldType::Func>(loc), func(name) {}
+
+ Func func;
+};
+
+class GlobalModuleField : public ModuleFieldMixin<ModuleFieldType::Global> {
+ public:
+ explicit GlobalModuleField(const Location& loc = Location(),
+ std::string_view name = std::string_view())
+ : ModuleFieldMixin<ModuleFieldType::Global>(loc), global(name) {}
+
+ Global global;
+};
+
+class ImportModuleField : public ModuleFieldMixin<ModuleFieldType::Import> {
+ public:
+ explicit ImportModuleField(const Location& loc = Location())
+ : ModuleFieldMixin<ModuleFieldType::Import>(loc) {}
+ explicit ImportModuleField(std::unique_ptr<Import> import,
+ const Location& loc = Location())
+ : ModuleFieldMixin<ModuleFieldType::Import>(loc),
+ import(std::move(import)) {}
+
+ std::unique_ptr<Import> import;
+};
+
+class ExportModuleField : public ModuleFieldMixin<ModuleFieldType::Export> {
+ public:
+ explicit ExportModuleField(const Location& loc = Location())
+ : ModuleFieldMixin<ModuleFieldType::Export>(loc) {}
+
+ Export export_;
+};
+
+class TypeModuleField : public ModuleFieldMixin<ModuleFieldType::Type> {
+ public:
+ explicit TypeModuleField(const Location& loc = Location())
+ : ModuleFieldMixin<ModuleFieldType::Type>(loc) {}
+
+ std::unique_ptr<TypeEntry> type;
+};
+
+class TableModuleField : public ModuleFieldMixin<ModuleFieldType::Table> {
+ public:
+ explicit TableModuleField(const Location& loc = Location(),
+ std::string_view name = std::string_view())
+ : ModuleFieldMixin<ModuleFieldType::Table>(loc), table(name) {}
+
+ Table table;
+};
+
+class ElemSegmentModuleField
+ : public ModuleFieldMixin<ModuleFieldType::ElemSegment> {
+ public:
+ explicit ElemSegmentModuleField(const Location& loc = Location(),
+ std::string_view name = std::string_view())
+ : ModuleFieldMixin<ModuleFieldType::ElemSegment>(loc),
+ elem_segment(name) {}
+
+ ElemSegment elem_segment;
+};
+
+class MemoryModuleField : public ModuleFieldMixin<ModuleFieldType::Memory> {
+ public:
+ explicit MemoryModuleField(const Location& loc = Location(),
+ std::string_view name = std::string_view())
+ : ModuleFieldMixin<ModuleFieldType::Memory>(loc), memory(name) {}
+
+ Memory memory;
+};
+
+class DataSegmentModuleField
+ : public ModuleFieldMixin<ModuleFieldType::DataSegment> {
+ public:
+ explicit DataSegmentModuleField(const Location& loc = Location(),
+ std::string_view name = std::string_view())
+ : ModuleFieldMixin<ModuleFieldType::DataSegment>(loc),
+ data_segment(name) {}
+
+ DataSegment data_segment;
+};
+
+class TagModuleField : public ModuleFieldMixin<ModuleFieldType::Tag> {
+ public:
+ explicit TagModuleField(const Location& loc = Location(),
+ std::string_view name = std::string_view())
+ : ModuleFieldMixin<ModuleFieldType::Tag>(loc), tag(name) {}
+
+ Tag tag;
+};
+
+class StartModuleField : public ModuleFieldMixin<ModuleFieldType::Start> {
+ public:
+ explicit StartModuleField(Var start = Var(), const Location& loc = Location())
+ : ModuleFieldMixin<ModuleFieldType::Start>(loc), start(start) {}
+
+ Var start;
+};
+
+struct Module {
+ Index GetFuncTypeIndex(const Var&) const;
+ Index GetFuncTypeIndex(const FuncDeclaration&) const;
+ Index GetFuncTypeIndex(const FuncSignature&) const;
+ const FuncType* GetFuncType(const Var&) const;
+ FuncType* GetFuncType(const Var&);
+ Index GetFuncIndex(const Var&) const;
+ const Func* GetFunc(const Var&) const;
+ Func* GetFunc(const Var&);
+ Index GetTableIndex(const Var&) const;
+ const Table* GetTable(const Var&) const;
+ Table* GetTable(const Var&);
+ Index GetMemoryIndex(const Var&) const;
+ const Memory* GetMemory(const Var&) const;
+ Memory* GetMemory(const Var&);
+ Index GetGlobalIndex(const Var&) const;
+ const Global* GetGlobal(const Var&) const;
+ Global* GetGlobal(const Var&);
+ const Export* GetExport(std::string_view) const;
+ Tag* GetTag(const Var&) const;
+ Index GetTagIndex(const Var&) const;
+ const DataSegment* GetDataSegment(const Var&) const;
+ DataSegment* GetDataSegment(const Var&);
+ Index GetDataSegmentIndex(const Var&) const;
+ const ElemSegment* GetElemSegment(const Var&) const;
+ ElemSegment* GetElemSegment(const Var&);
+ Index GetElemSegmentIndex(const Var&) const;
+
+ bool IsImport(ExternalKind kind, const Var&) const;
+ bool IsImport(const Export& export_) const {
+ return IsImport(export_.kind, export_.var);
+ }
+
+ // TODO(binji): move this into a builder class?
+ void AppendField(std::unique_ptr<DataSegmentModuleField>);
+ void AppendField(std::unique_ptr<ElemSegmentModuleField>);
+ void AppendField(std::unique_ptr<TagModuleField>);
+ void AppendField(std::unique_ptr<ExportModuleField>);
+ void AppendField(std::unique_ptr<FuncModuleField>);
+ void AppendField(std::unique_ptr<TypeModuleField>);
+ void AppendField(std::unique_ptr<GlobalModuleField>);
+ void AppendField(std::unique_ptr<ImportModuleField>);
+ void AppendField(std::unique_ptr<MemoryModuleField>);
+ void AppendField(std::unique_ptr<StartModuleField>);
+ void AppendField(std::unique_ptr<TableModuleField>);
+ void AppendField(std::unique_ptr<ModuleField>);
+ void AppendFields(ModuleFieldList*);
+
+ Location loc;
+ std::string name;
+ ModuleFieldList fields;
+
+ Index num_tag_imports = 0;
+ Index num_func_imports = 0;
+ Index num_table_imports = 0;
+ Index num_memory_imports = 0;
+ Index num_global_imports = 0;
+
+ // Cached for convenience; the pointers are shared with values that are
+ // stored in either ModuleField or Import.
+ std::vector<Tag*> tags;
+ std::vector<Func*> funcs;
+ std::vector<Global*> globals;
+ std::vector<Import*> imports;
+ std::vector<Export*> exports;
+ std::vector<TypeEntry*> types;
+ std::vector<Table*> tables;
+ std::vector<ElemSegment*> elem_segments;
+ std::vector<Memory*> memories;
+ std::vector<DataSegment*> data_segments;
+ std::vector<Var*> starts;
+
+ BindingHash tag_bindings;
+ BindingHash func_bindings;
+ BindingHash global_bindings;
+ BindingHash export_bindings;
+ BindingHash type_bindings;
+ BindingHash table_bindings;
+ BindingHash memory_bindings;
+ BindingHash data_segment_bindings;
+ BindingHash elem_segment_bindings;
+};
+
+enum class ScriptModuleType {
+ Text,
+ Binary,
+ Quoted,
+};
+
+// A ScriptModule is a module that may not yet be decoded. This allows for text
+// and binary parsing errors to be deferred until validation time.
+class ScriptModule {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(ScriptModule);
+ ScriptModule() = delete;
+ virtual ~ScriptModule() = default;
+
+ ScriptModuleType type() const { return type_; }
+ virtual const Location& location() const = 0;
+
+ protected:
+ explicit ScriptModule(ScriptModuleType type) : type_(type) {}
+
+ ScriptModuleType type_;
+};
+
+template <ScriptModuleType TypeEnum>
+class ScriptModuleMixin : public ScriptModule {
+ public:
+ static bool classof(const ScriptModule* script_module) {
+ return script_module->type() == TypeEnum;
+ }
+
+ ScriptModuleMixin() : ScriptModule(TypeEnum) {}
+};
+
+class TextScriptModule : public ScriptModuleMixin<ScriptModuleType::Text> {
+ public:
+ const Location& location() const override { return module.loc; }
+
+ Module module;
+};
+
+template <ScriptModuleType TypeEnum>
+class DataScriptModule : public ScriptModuleMixin<TypeEnum> {
+ public:
+ const Location& location() const override { return loc; }
+
+ Location loc;
+ std::string name;
+ std::vector<uint8_t> data;
+};
+
+using BinaryScriptModule = DataScriptModule<ScriptModuleType::Binary>;
+using QuotedScriptModule = DataScriptModule<ScriptModuleType::Quoted>;
+
+enum class ActionType {
+ Invoke,
+ Get,
+};
+
+class Action {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(Action);
+ Action() = delete;
+ virtual ~Action() = default;
+
+ ActionType type() const { return type_; }
+
+ Location loc;
+ Var module_var;
+ std::string name;
+
+ protected:
+ explicit Action(ActionType type, const Location& loc = Location())
+ : loc(loc), type_(type) {}
+
+ ActionType type_;
+};
+
+using ActionPtr = std::unique_ptr<Action>;
+
+template <ActionType TypeEnum>
+class ActionMixin : public Action {
+ public:
+ static bool classof(const Action* action) {
+ return action->type() == TypeEnum;
+ }
+
+ explicit ActionMixin(const Location& loc = Location())
+ : Action(TypeEnum, loc) {}
+};
+
+class GetAction : public ActionMixin<ActionType::Get> {
+ public:
+ explicit GetAction(const Location& loc = Location())
+ : ActionMixin<ActionType::Get>(loc) {}
+};
+
+class InvokeAction : public ActionMixin<ActionType::Invoke> {
+ public:
+ explicit InvokeAction(const Location& loc = Location())
+ : ActionMixin<ActionType::Invoke>(loc) {}
+
+ ConstVector args;
+};
+
+enum class CommandType {
+ Module,
+ ScriptModule,
+ Action,
+ Register,
+ AssertMalformed,
+ AssertInvalid,
+ AssertUnlinkable,
+ AssertUninstantiable,
+ AssertReturn,
+ AssertTrap,
+ AssertExhaustion,
+ AssertException,
+
+ First = Module,
+ Last = AssertException,
+};
+constexpr int kCommandTypeCount = WABT_ENUM_COUNT(CommandType);
+
+class Command {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(Command);
+ Command() = delete;
+ virtual ~Command() = default;
+
+ CommandType type;
+
+ protected:
+ explicit Command(CommandType type) : type(type) {}
+};
+
+template <CommandType TypeEnum>
+class CommandMixin : public Command {
+ public:
+ static bool classof(const Command* cmd) { return cmd->type == TypeEnum; }
+ CommandMixin() : Command(TypeEnum) {}
+};
+
+class ModuleCommand : public CommandMixin<CommandType::Module> {
+ public:
+ Module module;
+};
+
+class ScriptModuleCommand : public CommandMixin<CommandType::ScriptModule> {
+ public:
+ // Both the module and the script_module need to be stored since the module
+ // has the parsed information about the module, but the script_module has the
+ // original contents (binary or quoted).
+ Module module;
+ std::unique_ptr<ScriptModule> script_module;
+};
+
+template <CommandType TypeEnum>
+class ActionCommandBase : public CommandMixin<TypeEnum> {
+ public:
+ ActionPtr action;
+};
+
+using ActionCommand = ActionCommandBase<CommandType::Action>;
+
+class RegisterCommand : public CommandMixin<CommandType::Register> {
+ public:
+ RegisterCommand(std::string_view module_name, const Var& var)
+ : module_name(module_name), var(var) {}
+
+ std::string module_name;
+ Var var;
+};
+
+class AssertReturnCommand : public CommandMixin<CommandType::AssertReturn> {
+ public:
+ ActionPtr action;
+ ExpectationPtr expected;
+};
+
+template <CommandType TypeEnum>
+class AssertTrapCommandBase : public CommandMixin<TypeEnum> {
+ public:
+ ActionPtr action;
+ std::string text;
+};
+
+using AssertTrapCommand = AssertTrapCommandBase<CommandType::AssertTrap>;
+using AssertExhaustionCommand =
+ AssertTrapCommandBase<CommandType::AssertExhaustion>;
+
+template <CommandType TypeEnum>
+class AssertModuleCommand : public CommandMixin<TypeEnum> {
+ public:
+ std::unique_ptr<ScriptModule> module;
+ std::string text;
+};
+
+using AssertMalformedCommand =
+ AssertModuleCommand<CommandType::AssertMalformed>;
+using AssertInvalidCommand = AssertModuleCommand<CommandType::AssertInvalid>;
+using AssertUnlinkableCommand =
+ AssertModuleCommand<CommandType::AssertUnlinkable>;
+using AssertUninstantiableCommand =
+ AssertModuleCommand<CommandType::AssertUninstantiable>;
+
+class AssertExceptionCommand
+ : public CommandMixin<CommandType::AssertException> {
+ public:
+ ActionPtr action;
+};
+
+using CommandPtr = std::unique_ptr<Command>;
+using CommandPtrVector = std::vector<CommandPtr>;
+
+struct Script {
+ WABT_DISALLOW_COPY_AND_ASSIGN(Script);
+ Script() = default;
+
+ const Module* GetFirstModule() const;
+ Module* GetFirstModule();
+ const Module* GetModule(const Var&) const;
+
+ CommandPtrVector commands;
+ BindingHash module_bindings;
+};
+
+void MakeTypeBindingReverseMapping(
+ size_t num_types,
+ const BindingHash& bindings,
+ std::vector<std::string>* out_reverse_mapping);
+
+} // namespace wabt
+
+#endif /* WABT_IR_H_ */
diff --git a/third_party/wasm2c/include/wabt/leb128.h b/third_party/wasm2c/include/wabt/leb128.h
new file mode 100644
index 0000000000..e7290475b3
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/leb128.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_LEB128_H_
+#define WABT_LEB128_H_
+
+#include <cstdint>
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+class Stream;
+
+// Returns the length of the leb128.
+Offset U32Leb128Length(uint32_t value);
+
+void WriteU32Leb128(Stream* stream, uint32_t value, const char* desc);
+void WriteS32Leb128(Stream* stream, uint32_t value, const char* desc);
+void WriteU64Leb128(Stream* stream, uint64_t value, const char* desc);
+void WriteS64Leb128(Stream* stream, uint64_t value, const char* desc);
+void WriteFixedS32Leb128(Stream* stream, uint32_t value, const char* desc);
+void WriteFixedU32Leb128(Stream* stream, uint32_t value, const char* desc);
+
+Offset WriteU32Leb128At(Stream* stream,
+ Offset offset,
+ uint32_t value,
+ const char* desc);
+
+Offset WriteFixedU32Leb128At(Stream* stream,
+ Offset offset,
+ uint32_t value,
+ const char* desc);
+
+Offset WriteU32Leb128Raw(uint8_t* data, uint8_t* end, uint32_t value);
+Offset WriteFixedU32Leb128Raw(uint8_t* data, uint8_t* end, uint32_t value);
+
+// Convenience functions for writing enums as LEB128s.
+template <typename T>
+void WriteU32Leb128(Stream* stream, T value, const char* desc) {
+ WriteU32Leb128(stream, static_cast<uint32_t>(value), desc);
+}
+
+template <typename T>
+void WriteS32Leb128(Stream* stream, T value, const char* desc) {
+ WriteS32Leb128(stream, static_cast<uint32_t>(value), desc);
+}
+
+// Returns the length of the leb128.
+size_t ReadU32Leb128(const uint8_t* p, const uint8_t* end, uint32_t* out_value);
+size_t ReadU64Leb128(const uint8_t* p, const uint8_t* end, uint64_t* out_value);
+size_t ReadS32Leb128(const uint8_t* p, const uint8_t* end, uint32_t* out_value);
+size_t ReadS64Leb128(const uint8_t* p, const uint8_t* end, uint64_t* out_value);
+
+} // namespace wabt
+
+#endif // WABT_LEB128_H_
diff --git a/third_party/wasm2c/include/wabt/lexer-source-line-finder.h b/third_party/wasm2c/include/wabt/lexer-source-line-finder.h
new file mode 100644
index 0000000000..56719512d3
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/lexer-source-line-finder.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_LEXER_SOURCE_LINE_FINDER_H_
+#define WABT_LEXER_SOURCE_LINE_FINDER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "wabt/common.h"
+#include "wabt/lexer-source.h"
+#include "wabt/range.h"
+
+namespace wabt {
+
+class LexerSourceLineFinder {
+ public:
+ struct SourceLine {
+ std::string line;
+ int column_offset;
+ };
+
+ explicit LexerSourceLineFinder(std::unique_ptr<LexerSource>);
+
+ Result GetSourceLine(const Location& loc,
+ Offset max_line_length,
+ SourceLine* out_source_line);
+ Result GetLineOffsets(int line, OffsetRange* out_offsets);
+
+ private:
+ static OffsetRange ClampSourceLineOffsets(OffsetRange line_offset_range,
+ ColumnRange column_range,
+ Offset max_line_length);
+
+ bool IsLineCached(int line) const;
+ OffsetRange GetCachedLine(int line) const;
+
+ std::unique_ptr<LexerSource> source_;
+ std::vector<OffsetRange> line_ranges_;
+ Offset next_line_start_;
+ bool last_cr_; // Last read character was a '\r' (carriage return).
+ bool eof_;
+};
+
+} // namespace wabt
+
+#endif // WABT_LEXER_SOURCE_LINE_FINDER_H_
diff --git a/third_party/wasm2c/include/wabt/lexer-source.h b/third_party/wasm2c/include/wabt/lexer-source.h
new file mode 100644
index 0000000000..19e7d9a4b6
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/lexer-source.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_LEXER_SOURCE_H_
+#define WABT_LEXER_SOURCE_H_
+
+#include <cstddef>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "wabt/common.h"
+#include "wabt/range.h"
+
+namespace wabt {
+
+class LexerSource {
+ public:
+ LexerSource(const void* data, Offset size);
+
+ std::unique_ptr<LexerSource> Clone();
+ Result Tell(Offset* out_offset);
+ size_t Fill(void* dest, size_t size);
+ Result ReadRange(OffsetRange, std::vector<char>* out_data);
+ Result Seek(Offset offset);
+
+ WABT_DISALLOW_COPY_AND_ASSIGN(LexerSource);
+
+ const void* data() { return data_; }
+ Offset size() { return size_; }
+
+ private:
+ const void* data_;
+ Offset size_;
+ Offset read_offset_;
+};
+
+} // namespace wabt
+
+#endif // WABT_LEXER_SOURCE_H_
diff --git a/third_party/wasm2c/include/wabt/literal.h b/third_party/wasm2c/include/wabt/literal.h
new file mode 100644
index 0000000000..5eb8f4b0da
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/literal.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_LITERAL_H_
+#define WABT_LITERAL_H_
+
+#include <cstdint>
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+// These functions all return Result::Ok on success and Result::Error on
+// failure.
+//
+// NOTE: the functions are written for use with wast-lexer, assuming that the
+// literal has already matched the patterns defined there. As a result, the
+// only validation that is done is for overflow, not for otherwise bogus input.
+
+enum class LiteralType {
+ Int,
+ Float,
+ Hexfloat,
+ Infinity,
+ Nan,
+};
+
+enum class ParseIntType {
+ UnsignedOnly = 0,
+ SignedAndUnsigned = 1,
+};
+
+/* Size of char buffer required to hold hex representation of a float/double */
+#define WABT_MAX_FLOAT_HEX 20
+#define WABT_MAX_DOUBLE_HEX 40
+
+Result ParseHexdigit(char c, uint32_t* out);
+Result ParseInt8(const char* s,
+ const char* end,
+ uint8_t* out,
+ ParseIntType parse_type);
+Result ParseInt16(const char* s,
+ const char* end,
+ uint16_t* out,
+ ParseIntType parse_type);
+Result ParseInt32(const char* s,
+ const char* end,
+ uint32_t* out,
+ ParseIntType parse_type);
+Result ParseInt64(const char* s,
+ const char* end,
+ uint64_t* out,
+ ParseIntType parse_type);
+Result ParseUint64(const char* s, const char* end, uint64_t* out);
+Result ParseUint128(const char* s, const char* end, v128* out);
+Result ParseFloat(LiteralType literal_type,
+ const char* s,
+ const char* end,
+ uint32_t* out_bits);
+Result ParseDouble(LiteralType literal_type,
+ const char* s,
+ const char* end,
+ uint64_t* out_bits);
+
+// Same as above but taking a string_view
+inline Result ParseInt8(std::string_view v,
+ uint8_t* out,
+ ParseIntType parse_type) {
+ return ParseInt8(v.data(), v.data() + v.size(), out, parse_type);
+}
+
+inline Result ParseInt16(std::string_view v,
+ uint16_t* out,
+ ParseIntType parse_type) {
+ return ParseInt16(v.data(), v.data() + v.size(), out, parse_type);
+}
+
+inline Result ParseInt32(std::string_view v,
+ uint32_t* out,
+ ParseIntType parse_type) {
+ return ParseInt32(v.data(), v.data() + v.size(), out, parse_type);
+}
+
+inline Result ParseInt64(std::string_view v,
+ uint64_t* out,
+ ParseIntType parse_type) {
+ return ParseInt64(v.data(), v.data() + v.size(), out, parse_type);
+}
+
+inline Result ParseUint64(std::string_view v, uint64_t* out) {
+ return ParseUint64(v.data(), v.data() + v.size(), out);
+}
+
+inline Result ParseUint128(std::string_view v, v128* out) {
+ return ParseUint128(v.data(), v.data() + v.size(), out);
+}
+
+inline Result ParseFloat(LiteralType literal_type,
+ std::string_view v,
+ uint32_t* out_bits) {
+ return ParseFloat(literal_type, v.data(), v.data() + v.size(), out_bits);
+}
+
+inline Result ParseDouble(LiteralType literal_type,
+ std::string_view v,
+ uint64_t* out_bits) {
+ return ParseDouble(literal_type, v.data(), v.data() + v.size(), out_bits);
+}
+
+void WriteFloatHex(char* buffer, size_t size, uint32_t bits);
+void WriteDoubleHex(char* buffer, size_t size, uint64_t bits);
+void WriteUint128(char* buffer, size_t size, v128 bits);
+
+} // namespace wabt
+
+#endif /* WABT_LITERAL_H_ */
diff --git a/third_party/wasm2c/include/wabt/opcode-code-table.h b/third_party/wasm2c/include/wabt/opcode-code-table.h
new file mode 100644
index 0000000000..13c5838ea6
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/opcode-code-table.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2018 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_OPCODE_CODE_TABLE_H_
+#define WABT_OPCODE_CODE_TABLE_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define WABT_OPCODE_CODE_TABLE_SIZE 131072
+
+/*
+ * Number of bits required to store an opcode
+ */
+#define MAX_OPCODE_BITS 9
+
+/* This structure is defined in C because C++ doesn't (yet) allow you to use
+ * designated array initializers, i.e. [10] = {foo}.
+ */
+extern uint32_t WabtOpcodeCodeTable[WABT_OPCODE_CODE_TABLE_SIZE];
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* WABT_OPCODE_CODE_TABLE_H_ */
diff --git a/third_party/wasm2c/include/wabt/opcode.def b/third_party/wasm2c/include/wabt/opcode.def
new file mode 100644
index 0000000000..e10f9cba82
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/opcode.def
@@ -0,0 +1,593 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_OPCODE
+#error "You must define WABT_OPCODE before including this file."
+#endif
+
+/* *** NOTE *** This list must be kept sorted so it can be binary searched */
+
+/*
+ * tr: result type
+ * t1: type of the 1st parameter
+ * t2: type of the 2nd parameter
+ * t3: type of the 3rd parameter
+ * m: memory size of the operation, if any
+ * prefix: the 1-byte opcode prefix, if any
+ * code: opcode
+ * Name: used to generate the opcode enum
+ * text: a string of the opcode name in the text format
+ * decomp: an optional friendly version of text, used for decompilation.
+ *
+ * tr t1 t2 t3 m prefix code Name text
+ * ========================================================== */
+
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x00, Unreachable, "unreachable", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x01, Nop, "nop", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x02, Block, "block", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x03, Loop, "loop", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x04, If, "if", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x05, Else, "else", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x06, Try, "try", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x07, Catch, "catch", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x08, Throw, "throw", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x09, Rethrow, "rethrow", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x0b, End, "end", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x0c, Br, "br", "")
+WABT_OPCODE(___, I32, ___, ___, 0, 0, 0x0d, BrIf, "br_if", "")
+WABT_OPCODE(___, I32, ___, ___, 0, 0, 0x0e, BrTable, "br_table", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x0f, Return, "return", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x10, Call, "call", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x11, CallIndirect, "call_indirect", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x12, ReturnCall, "return_call", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x13, ReturnCallIndirect, "return_call_indirect", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x14, CallRef, "call_ref", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x18, Delegate, "delegate", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x19, CatchAll, "catch_all", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x1a, Drop, "drop", "")
+WABT_OPCODE(___, ___, ___, I32, 0, 0, 0x1b, Select, "select", "")
+WABT_OPCODE(___, ___, ___, I32, 0, 0, 0x1c, SelectT, "select", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x20, LocalGet, "local.get", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x21, LocalSet, "local.set", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x22, LocalTee, "local.tee", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x23, GlobalGet, "global.get", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0x24, GlobalSet, "global.set", "")
+WABT_OPCODE(I32, I32, ___, ___, 4, 0, 0x28, I32Load, "i32.load", "")
+WABT_OPCODE(I64, I32, ___, ___, 8, 0, 0x29, I64Load, "i64.load", "")
+WABT_OPCODE(F32, I32, ___, ___, 4, 0, 0x2a, F32Load, "f32.load", "")
+WABT_OPCODE(F64, I32, ___, ___, 8, 0, 0x2b, F64Load, "f64.load", "")
+WABT_OPCODE(I32, I32, ___, ___, 1, 0, 0x2c, I32Load8S, "i32.load8_s", "")
+WABT_OPCODE(I32, I32, ___, ___, 1, 0, 0x2d, I32Load8U, "i32.load8_u", "")
+WABT_OPCODE(I32, I32, ___, ___, 2, 0, 0x2e, I32Load16S, "i32.load16_s", "")
+WABT_OPCODE(I32, I32, ___, ___, 2, 0, 0x2f, I32Load16U, "i32.load16_u", "")
+WABT_OPCODE(I64, I32, ___, ___, 1, 0, 0x30, I64Load8S, "i64.load8_s", "")
+WABT_OPCODE(I64, I32, ___, ___, 1, 0, 0x31, I64Load8U, "i64.load8_u", "")
+WABT_OPCODE(I64, I32, ___, ___, 2, 0, 0x32, I64Load16S, "i64.load16_s", "")
+WABT_OPCODE(I64, I32, ___, ___, 2, 0, 0x33, I64Load16U, "i64.load16_u", "")
+WABT_OPCODE(I64, I32, ___, ___, 4, 0, 0x34, I64Load32S, "i64.load32_s", "")
+WABT_OPCODE(I64, I32, ___, ___, 4, 0, 0x35, I64Load32U, "i64.load32_u", "")
+WABT_OPCODE(___, I32, I32, ___, 4, 0, 0x36, I32Store, "i32.store", "")
+WABT_OPCODE(___, I32, I64, ___, 8, 0, 0x37, I64Store, "i64.store", "")
+WABT_OPCODE(___, I32, F32, ___, 4, 0, 0x38, F32Store, "f32.store", "")
+WABT_OPCODE(___, I32, F64, ___, 8, 0, 0x39, F64Store, "f64.store", "")
+WABT_OPCODE(___, I32, I32, ___, 1, 0, 0x3a, I32Store8, "i32.store8", "")
+WABT_OPCODE(___, I32, I32, ___, 2, 0, 0x3b, I32Store16, "i32.store16", "")
+WABT_OPCODE(___, I32, I64, ___, 1, 0, 0x3c, I64Store8, "i64.store8", "")
+WABT_OPCODE(___, I32, I64, ___, 2, 0, 0x3d, I64Store16, "i64.store16", "")
+WABT_OPCODE(___, I32, I64, ___, 4, 0, 0x3e, I64Store32, "i64.store32", "")
+WABT_OPCODE(I32, ___, ___, ___, 0, 0, 0x3f, MemorySize, "memory.size", "")
+WABT_OPCODE(I32, I32, ___, ___, 0, 0, 0x40, MemoryGrow, "memory.grow", "")
+WABT_OPCODE(I32, ___, ___, ___, 0, 0, 0x41, I32Const, "i32.const", "")
+WABT_OPCODE(I64, ___, ___, ___, 0, 0, 0x42, I64Const, "i64.const", "")
+WABT_OPCODE(F32, ___, ___, ___, 0, 0, 0x43, F32Const, "f32.const", "")
+WABT_OPCODE(F64, ___, ___, ___, 0, 0, 0x44, F64Const, "f64.const", "")
+WABT_OPCODE(I32, I32, ___, ___, 0, 0, 0x45, I32Eqz, "i32.eqz", "eqz")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x46, I32Eq, "i32.eq", "==")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x47, I32Ne, "i32.ne", "!=")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x48, I32LtS, "i32.lt_s", "<")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x49, I32LtU, "i32.lt_u", "<")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x4a, I32GtS, "i32.gt_s", ">")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x4b, I32GtU, "i32.gt_u", ">")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x4c, I32LeS, "i32.le_s", "<=")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x4d, I32LeU, "i32.le_u", "<=")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x4e, I32GeS, "i32.ge_s", ">=")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x4f, I32GeU, "i32.ge_u", ">=")
+WABT_OPCODE(I32, I64, ___, ___, 0, 0, 0x50, I64Eqz, "i64.eqz", "eqz")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x51, I64Eq, "i64.eq", "==")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x52, I64Ne, "i64.ne", "!=")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x53, I64LtS, "i64.lt_s", "<")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x54, I64LtU, "i64.lt_u", "<")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x55, I64GtS, "i64.gt_s", ">")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x56, I64GtU, "i64.gt_u", ">")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x57, I64LeS, "i64.le_s", "<=")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x58, I64LeU, "i64.le_u", "<=")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x59, I64GeS, "i64.ge_s", ">=")
+WABT_OPCODE(I32, I64, I64, ___, 0, 0, 0x5a, I64GeU, "i64.ge_u", ">=")
+WABT_OPCODE(I32, F32, F32, ___, 0, 0, 0x5b, F32Eq, "f32.eq", "==")
+WABT_OPCODE(I32, F32, F32, ___, 0, 0, 0x5c, F32Ne, "f32.ne", "!=")
+WABT_OPCODE(I32, F32, F32, ___, 0, 0, 0x5d, F32Lt, "f32.lt", "<")
+WABT_OPCODE(I32, F32, F32, ___, 0, 0, 0x5e, F32Gt, "f32.gt", ">")
+WABT_OPCODE(I32, F32, F32, ___, 0, 0, 0x5f, F32Le, "f32.le", "<=")
+WABT_OPCODE(I32, F32, F32, ___, 0, 0, 0x60, F32Ge, "f32.ge", ">=")
+WABT_OPCODE(I32, F64, F64, ___, 0, 0, 0x61, F64Eq, "f64.eq", "==")
+WABT_OPCODE(I32, F64, F64, ___, 0, 0, 0x62, F64Ne, "f64.ne", "!=")
+WABT_OPCODE(I32, F64, F64, ___, 0, 0, 0x63, F64Lt, "f64.lt", "<")
+WABT_OPCODE(I32, F64, F64, ___, 0, 0, 0x64, F64Gt, "f64.gt", ">")
+WABT_OPCODE(I32, F64, F64, ___, 0, 0, 0x65, F64Le, "f64.le", "<=")
+WABT_OPCODE(I32, F64, F64, ___, 0, 0, 0x66, F64Ge, "f64.ge", ">=")
+WABT_OPCODE(I32, I32, ___, ___, 0, 0, 0x67, I32Clz, "i32.clz", "clz")
+WABT_OPCODE(I32, I32, ___, ___, 0, 0, 0x68, I32Ctz, "i32.ctz", "ctz")
+WABT_OPCODE(I32, I32, ___, ___, 0, 0, 0x69, I32Popcnt, "i32.popcnt", "popcnt")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x6a, I32Add, "i32.add", "+")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x6b, I32Sub, "i32.sub", "-")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x6c, I32Mul, "i32.mul", "*")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x6d, I32DivS, "i32.div_s", "/")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x6e, I32DivU, "i32.div_u", "/")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x6f, I32RemS, "i32.rem_s", "%")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x70, I32RemU, "i32.rem_u", "%")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x71, I32And, "i32.and", "&")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x72, I32Or, "i32.or", "|")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x73, I32Xor, "i32.xor", "^")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x74, I32Shl, "i32.shl", "<<")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x75, I32ShrS, "i32.shr_s", ">>")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x76, I32ShrU, "i32.shr_u", ">>")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x77, I32Rotl, "i32.rotl", "<<")
+WABT_OPCODE(I32, I32, I32, ___, 0, 0, 0x78, I32Rotr, "i32.rotr", ">>")
+WABT_OPCODE(I64, I64, ___, ___, 0, 0, 0x79, I64Clz, "i64.clz", "clz")
+WABT_OPCODE(I64, I64, ___, ___, 0, 0, 0x7a, I64Ctz, "i64.ctz", "ctz")
+WABT_OPCODE(I64, I64, ___, ___, 0, 0, 0x7b, I64Popcnt, "i64.popcnt", "popcnt")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x7c, I64Add, "i64.add", "+")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x7d, I64Sub, "i64.sub", "-")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x7e, I64Mul, "i64.mul", "*")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x7f, I64DivS, "i64.div_s", "/")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x80, I64DivU, "i64.div_u", "/")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x81, I64RemS, "i64.rem_s", "%")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x82, I64RemU, "i64.rem_u", "%")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x83, I64And, "i64.and", "&")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x84, I64Or, "i64.or", "|")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x85, I64Xor, "i64.xor", "^")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x86, I64Shl, "i64.shl", "<<")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x87, I64ShrS, "i64.shr_s", ">>")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x88, I64ShrU, "i64.shr_u", ">>")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x89, I64Rotl, "i64.rotl", "<<")
+WABT_OPCODE(I64, I64, I64, ___, 0, 0, 0x8a, I64Rotr, "i64.rotr", ">>")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x8b, F32Abs, "f32.abs", "abs")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x8c, F32Neg, "f32.neg", "-")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x8d, F32Ceil, "f32.ceil", "ceil")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x8e, F32Floor, "f32.floor", "floor")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x8f, F32Trunc, "f32.trunc", "trunc")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x90, F32Nearest, "f32.nearest", "nearest")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x91, F32Sqrt, "f32.sqrt", "sqrt")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x92, F32Add, "f32.add", "+")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x93, F32Sub, "f32.sub", "-")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x94, F32Mul, "f32.mul", "*")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x95, F32Div, "f32.div", "/")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x96, F32Min, "f32.min", "min")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x97, F32Max, "f32.max", "max")
+WABT_OPCODE(F32, F32, F32, ___, 0, 0, 0x98, F32Copysign, "f32.copysign", "copysign")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0x99, F64Abs, "f64.abs", "abs")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0x9a, F64Neg, "f64.neg", "-")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0x9b, F64Ceil, "f64.ceil", "ceil")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0x9c, F64Floor, "f64.floor", "floor")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0x9d, F64Trunc, "f64.trunc", "trunc")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0x9e, F64Nearest, "f64.nearest", "nearest")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0x9f, F64Sqrt, "f64.sqrt", "sqrt")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0xa0, F64Add, "f64.add", "+")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0xa1, F64Sub, "f64.sub", "-")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0xa2, F64Mul, "f64.mul", "*")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0xa3, F64Div, "f64.div", "/")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0xa4, F64Min, "f64.min", "min")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0xa5, F64Max, "f64.max", "max")
+WABT_OPCODE(F64, F64, F64, ___, 0, 0, 0xa6, F64Copysign, "f64.copysign", "copysign")
+WABT_OPCODE(I32, I64, ___, ___, 0, 0, 0xa7, I32WrapI64, "i32.wrap_i64", "")
+WABT_OPCODE(I32, F32, ___, ___, 0, 0, 0xa8, I32TruncF32S, "i32.trunc_f32_s", "")
+WABT_OPCODE(I32, F32, ___, ___, 0, 0, 0xa9, I32TruncF32U, "i32.trunc_f32_u", "")
+WABT_OPCODE(I32, F64, ___, ___, 0, 0, 0xaa, I32TruncF64S, "i32.trunc_f64_s", "")
+WABT_OPCODE(I32, F64, ___, ___, 0, 0, 0xab, I32TruncF64U, "i32.trunc_f64_u", "")
+WABT_OPCODE(I64, I32, ___, ___, 0, 0, 0xac, I64ExtendI32S, "i64.extend_i32_s", "")
+WABT_OPCODE(I64, I32, ___, ___, 0, 0, 0xad, I64ExtendI32U, "i64.extend_i32_u", "")
+WABT_OPCODE(I64, F32, ___, ___, 0, 0, 0xae, I64TruncF32S, "i64.trunc_f32_s", "")
+WABT_OPCODE(I64, F32, ___, ___, 0, 0, 0xaf, I64TruncF32U, "i64.trunc_f32_u", "")
+WABT_OPCODE(I64, F64, ___, ___, 0, 0, 0xb0, I64TruncF64S, "i64.trunc_f64_s", "")
+WABT_OPCODE(I64, F64, ___, ___, 0, 0, 0xb1, I64TruncF64U, "i64.trunc_f64_u", "")
+WABT_OPCODE(F32, I32, ___, ___, 0, 0, 0xb2, F32ConvertI32S, "f32.convert_i32_s", "")
+WABT_OPCODE(F32, I32, ___, ___, 0, 0, 0xb3, F32ConvertI32U, "f32.convert_i32_u", "")
+WABT_OPCODE(F32, I64, ___, ___, 0, 0, 0xb4, F32ConvertI64S, "f32.convert_i64_s", "")
+WABT_OPCODE(F32, I64, ___, ___, 0, 0, 0xb5, F32ConvertI64U, "f32.convert_i64_u", "")
+WABT_OPCODE(F32, F64, ___, ___, 0, 0, 0xb6, F32DemoteF64, "f32.demote_f64", "")
+WABT_OPCODE(F64, I32, ___, ___, 0, 0, 0xb7, F64ConvertI32S, "f64.convert_i32_s", "")
+WABT_OPCODE(F64, I32, ___, ___, 0, 0, 0xb8, F64ConvertI32U, "f64.convert_i32_u", "")
+WABT_OPCODE(F64, I64, ___, ___, 0, 0, 0xb9, F64ConvertI64S, "f64.convert_i64_s", "")
+WABT_OPCODE(F64, I64, ___, ___, 0, 0, 0xba, F64ConvertI64U, "f64.convert_i64_u", "")
+WABT_OPCODE(F64, F32, ___, ___, 0, 0, 0xbb, F64PromoteF32, "f64.promote_f32", "")
+WABT_OPCODE(I32, F32, ___, ___, 0, 0, 0xbc, I32ReinterpretF32, "i32.reinterpret_f32", "")
+WABT_OPCODE(I64, F64, ___, ___, 0, 0, 0xbd, I64ReinterpretF64, "i64.reinterpret_f64", "")
+WABT_OPCODE(F32, I32, ___, ___, 0, 0, 0xbe, F32ReinterpretI32, "f32.reinterpret_i32", "")
+WABT_OPCODE(F64, I64, ___, ___, 0, 0, 0xbf, F64ReinterpretI64, "f64.reinterpret_i64", "")
+
+/* Sign-extension opcodes (--enable-sign-extension) */
+WABT_OPCODE(I32, I32, ___, ___, 0, 0, 0xC0, I32Extend8S, "i32.extend8_s", "")
+WABT_OPCODE(I32, I32, ___, ___, 0, 0, 0xC1, I32Extend16S, "i32.extend16_s", "")
+WABT_OPCODE(I64, I64, ___, ___, 0, 0, 0xC2, I64Extend8S, "i64.extend8_s", "")
+WABT_OPCODE(I64, I64, ___, ___, 0, 0, 0xC3, I64Extend16S, "i64.extend16_s", "")
+WABT_OPCODE(I64, I64, ___, ___, 0, 0, 0xC4, I64Extend32S, "i64.extend32_s", "")
+
+/* Interpreter-only opcodes */
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe0, InterpAlloca, "alloca", "")
+WABT_OPCODE(___, I32, ___, ___, 0, 0, 0xe1, InterpBrUnless, "br_unless", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe2, InterpCallImport, "call_import", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe3, InterpData, "data", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe4, InterpDropKeep, "drop_keep", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe5, InterpCatchDrop, "catch_drop", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xe6, InterpAdjustFrameForReturnCall, "adjust_frame_for_return_call", "")
+
+/* Saturating float-to-int opcodes (--enable-saturating-float-to-int) */
+WABT_OPCODE(I32, F32, ___, ___, 0, 0xfc, 0x00, I32TruncSatF32S, "i32.trunc_sat_f32_s", "")
+WABT_OPCODE(I32, F32, ___, ___, 0, 0xfc, 0x01, I32TruncSatF32U, "i32.trunc_sat_f32_u", "")
+WABT_OPCODE(I32, F64, ___, ___, 0, 0xfc, 0x02, I32TruncSatF64S, "i32.trunc_sat_f64_s", "")
+WABT_OPCODE(I32, F64, ___, ___, 0, 0xfc, 0x03, I32TruncSatF64U, "i32.trunc_sat_f64_u", "")
+WABT_OPCODE(I64, F32, ___, ___, 0, 0xfc, 0x04, I64TruncSatF32S, "i64.trunc_sat_f32_s", "")
+WABT_OPCODE(I64, F32, ___, ___, 0, 0xfc, 0x05, I64TruncSatF32U, "i64.trunc_sat_f32_u", "")
+WABT_OPCODE(I64, F64, ___, ___, 0, 0xfc, 0x06, I64TruncSatF64S, "i64.trunc_sat_f64_s", "")
+WABT_OPCODE(I64, F64, ___, ___, 0, 0xfc, 0x07, I64TruncSatF64U, "i64.trunc_sat_f64_u", "")
+
+/* Bulk-memory */
+WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x08, MemoryInit, "memory.init", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0xfc, 0x09, DataDrop, "data.drop", "")
+WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x0a, MemoryCopy,"memory.copy", "")
+WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x0b, MemoryFill, "memory.fill", "")
+WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x0c, TableInit, "table.init", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0xfc, 0x0d, ElemDrop, "elem.drop", "")
+WABT_OPCODE(___, I32, I32, I32, 0, 0xfc, 0x0e, TableCopy, "table.copy", "")
+
+/* Reference types */
+WABT_OPCODE(___, I32, ___, ___, 0, 0, 0x25, TableGet, "table.get", "")
+WABT_OPCODE(___, I32, ___, ___, 0, 0, 0x26, TableSet, "table.set", "")
+WABT_OPCODE(___, ___, I32, ___, 0, 0xfc, 0x0f, TableGrow, "table.grow", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0xfc, 0x10, TableSize, "table.size", "")
+WABT_OPCODE(___, I32, ___, I32, 0, 0xfc, 0x11, TableFill, "table.fill", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd0, RefNull, "ref.null", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd1, RefIsNull, "ref.is_null", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0, 0xd2, RefFunc, "ref.func", "")
+
+/* Simd opcodes */
+WABT_OPCODE(V128, I32, ___, ___, 16, 0xfd, 0x00, V128Load, "v128.load", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x01, V128Load8X8S, "v128.load8x8_s", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x02, V128Load8X8U, "v128.load8x8_u", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x03, V128Load16X4S, "v128.load16x4_s", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x04, V128Load16X4U, "v128.load16x4_u", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x05, V128Load32X2S, "v128.load32x2_s", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x06, V128Load32X2U, "v128.load32x2_u", "")
+WABT_OPCODE(V128, I32, ___, ___, 1, 0xfd, 0x07, V128Load8Splat, "v128.load8_splat", "")
+WABT_OPCODE(V128, I32, ___, ___, 2, 0xfd, 0x08, V128Load16Splat, "v128.load16_splat", "")
+WABT_OPCODE(V128, I32, ___, ___, 4, 0xfd, 0x09, V128Load32Splat, "v128.load32_splat", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x0a, V128Load64Splat, "v128.load64_splat", "")
+WABT_OPCODE(___, I32, V128, ___, 16, 0xfd, 0x0b, V128Store, "v128.store", "")
+WABT_OPCODE(V128, ___, ___, ___, 0, 0xfd, 0x0c, V128Const, "v128.const", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x0d, I8X16Shuffle, "i8x16.shuffle", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x0e, I8X16Swizzle, "i8x16.swizzle", "")
+WABT_OPCODE(V128, I32, ___, ___, 0, 0xfd, 0x0f, I8X16Splat, "i8x16.splat", "")
+WABT_OPCODE(V128, I32, ___, ___, 0, 0xfd, 0x10, I16X8Splat, "i16x8.splat", "")
+WABT_OPCODE(V128, I32, ___, ___, 0, 0xfd, 0x11, I32X4Splat, "i32x4.splat", "")
+WABT_OPCODE(V128, I64, ___, ___, 0, 0xfd, 0x12, I64X2Splat, "i64x2.splat", "")
+WABT_OPCODE(V128, F32, ___, ___, 0, 0xfd, 0x13, F32X4Splat, "f32x4.splat", "")
+WABT_OPCODE(V128, F64, ___, ___, 0, 0xfd, 0x14, F64X2Splat, "f64x2.splat", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x15, I8X16ExtractLaneS, "i8x16.extract_lane_s", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x16, I8X16ExtractLaneU, "i8x16.extract_lane_u", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x17, I8X16ReplaceLane, "i8x16.replace_lane", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x18, I16X8ExtractLaneS, "i16x8.extract_lane_s", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x19, I16X8ExtractLaneU, "i16x8.extract_lane_u", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x1a, I16X8ReplaceLane, "i16x8.replace_lane", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x1b, I32X4ExtractLane, "i32x4.extract_lane", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x1c, I32X4ReplaceLane, "i32x4.replace_lane", "")
+WABT_OPCODE(I64, V128, ___, ___, 0, 0xfd, 0x1d, I64X2ExtractLane, "i64x2.extract_lane", "")
+WABT_OPCODE(V128, V128, I64, ___, 0, 0xfd, 0x1e, I64X2ReplaceLane, "i64x2.replace_lane", "")
+WABT_OPCODE(F32, V128, ___, ___, 0, 0xfd, 0x1f, F32X4ExtractLane, "f32x4.extract_lane", "")
+WABT_OPCODE(V128, V128, F32, ___, 0, 0xfd, 0x20, F32X4ReplaceLane, "f32x4.replace_lane", "")
+WABT_OPCODE(F64, V128, ___, ___, 0, 0xfd, 0x21, F64X2ExtractLane, "f64x2.extract_lane", "")
+WABT_OPCODE(V128, V128, F64, ___, 0, 0xfd, 0x22, F64X2ReplaceLane, "f64x2.replace_lane", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x23, I8X16Eq, "i8x16.eq", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x24, I8X16Ne, "i8x16.ne", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x25, I8X16LtS, "i8x16.lt_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x26, I8X16LtU, "i8x16.lt_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x27, I8X16GtS, "i8x16.gt_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x28, I8X16GtU, "i8x16.gt_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x29, I8X16LeS, "i8x16.le_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x2a, I8X16LeU, "i8x16.le_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x2b, I8X16GeS, "i8x16.ge_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x2c, I8X16GeU, "i8x16.ge_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x2d, I16X8Eq, "i16x8.eq", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x2e, I16X8Ne, "i16x8.ne", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x2f, I16X8LtS, "i16x8.lt_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x30, I16X8LtU, "i16x8.lt_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x31, I16X8GtS, "i16x8.gt_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x32, I16X8GtU, "i16x8.gt_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x33, I16X8LeS, "i16x8.le_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x34, I16X8LeU, "i16x8.le_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x35, I16X8GeS, "i16x8.ge_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x36, I16X8GeU, "i16x8.ge_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x37, I32X4Eq, "i32x4.eq", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x38, I32X4Ne, "i32x4.ne", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x39, I32X4LtS, "i32x4.lt_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x3a, I32X4LtU, "i32x4.lt_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x3b, I32X4GtS, "i32x4.gt_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x3c, I32X4GtU, "i32x4.gt_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x3d, I32X4LeS, "i32x4.le_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x3e, I32X4LeU, "i32x4.le_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x3f, I32X4GeS, "i32x4.ge_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x40, I32X4GeU, "i32x4.ge_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x41, F32X4Eq, "f32x4.eq", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x42, F32X4Ne, "f32x4.ne", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x43, F32X4Lt, "f32x4.lt", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x44, F32X4Gt, "f32x4.gt", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x45, F32X4Le, "f32x4.le", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x46, F32X4Ge, "f32x4.ge", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x47, F64X2Eq, "f64x2.eq", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x48, F64X2Ne, "f64x2.ne", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x49, F64X2Lt, "f64x2.lt", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x4a, F64X2Gt, "f64x2.gt", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x4b, F64X2Le, "f64x2.le", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x4c, F64X2Ge, "f64x2.ge", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x4d, V128Not, "v128.not", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x4e, V128And, "v128.and", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x4f, V128Andnot, "v128.andnot", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x50, V128Or, "v128.or", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x51, V128Xor, "v128.xor", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x52, V128BitSelect, "v128.bitselect", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x53, V128AnyTrue, "v128.any_true", "")
+WABT_OPCODE(V128, I32, V128, ___, 1, 0xfd, 0x54, V128Load8Lane, "v128.load8_lane", "")
+WABT_OPCODE(V128, I32, V128, ___, 2, 0xfd, 0x55, V128Load16Lane, "v128.load16_lane", "")
+WABT_OPCODE(V128, I32, V128, ___, 4, 0xfd, 0x56, V128Load32Lane, "v128.load32_lane", "")
+WABT_OPCODE(V128, I32, V128, ___, 8, 0xfd, 0x57, V128Load64Lane, "v128.load64_lane", "")
+WABT_OPCODE(___, I32, V128, ___, 1, 0xfd, 0x58, V128Store8Lane, "v128.store8_lane", "")
+WABT_OPCODE(___, I32, V128, ___, 2, 0xfd, 0x59, V128Store16Lane, "v128.store16_lane", "")
+WABT_OPCODE(___, I32, V128, ___, 4, 0xfd, 0x5a, V128Store32Lane, "v128.store32_lane", "")
+WABT_OPCODE(___, I32, V128, ___, 8, 0xfd, 0x5b, V128Store64Lane, "v128.store64_lane", "")
+WABT_OPCODE(V128, I32, ___, ___, 4, 0xfd, 0x5c, V128Load32Zero, "v128.load32_zero", "")
+WABT_OPCODE(V128, I32, ___, ___, 8, 0xfd, 0x5d, V128Load64Zero, "v128.load64_zero", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x5e, F32X4DemoteF64X2Zero, "f32x4.demote_f64x2_zero", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x5f, F64X2PromoteLowF32X4, "f64x2.promote_low_f32x4", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x60, I8X16Abs, "i8x16.abs", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x61, I8X16Neg, "i8x16.neg", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x62, I8X16Popcnt, "i8x16.popcnt", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x63, I8X16AllTrue, "i8x16.all_true", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x64, I8X16Bitmask, "i8x16.bitmask", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x65, I8X16NarrowI16X8S, "i8x16.narrow_i16x8_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x66, I8X16NarrowI16X8U, "i8x16.narrow_i16x8_u", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x6b, I8X16Shl, "i8x16.shl", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x6c, I8X16ShrS, "i8x16.shr_s", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x6d, I8X16ShrU, "i8x16.shr_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x6e, I8X16Add, "i8x16.add", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x6f, I8X16AddSatS, "i8x16.add_sat_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x70, I8X16AddSatU, "i8x16.add_sat_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x71, I8X16Sub, "i8x16.sub", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x72, I8X16SubSatS, "i8x16.sub_sat_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x73, I8X16SubSatU, "i8x16.sub_sat_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x76, I8X16MinS, "i8x16.min_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x77, I8X16MinU, "i8x16.min_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x78, I8X16MaxS, "i8x16.max_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x79, I8X16MaxU, "i8x16.max_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x7b, I8X16AvgrU, "i8x16.avgr_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x7c, I16X8ExtaddPairwiseI8X16S, "i16x8.extadd_pairwise_i8x16_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x7d, I16X8ExtaddPairwiseI8X16U, "i16x8.extadd_pairwise_i8x16_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x7e, I32X4ExtaddPairwiseI16X8S, "i32x4.extadd_pairwise_i16x8_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x7f, I32X4ExtaddPairwiseI16X8U, "i32x4.extadd_pairwise_i16x8_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x80, I16X8Abs, "i16x8.abs", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x81, I16X8Neg, "i16x8.neg", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x82, I16X8Q15mulrSatS, "i16x8.q15mulr_sat_s", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x83, I16X8AllTrue, "i16x8.all_true", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x84, I16X8Bitmask, "i16x8.bitmask", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x85, I16X8NarrowI32X4S, "i16x8.narrow_i32x4_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x86, I16X8NarrowI32X4U, "i16x8.narrow_i32x4_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x87, I16X8ExtendLowI8X16S, "i16x8.extend_low_i8x16_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x88, I16X8ExtendHighI8X16S, "i16x8.extend_high_i8x16_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x89, I16X8ExtendLowI8X16U, "i16x8.extend_low_i8x16_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x8a, I16X8ExtendHighI8X16U, "i16x8.extend_high_i8x16_u", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x8b, I16X8Shl, "i16x8.shl", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x8c, I16X8ShrS, "i16x8.shr_s", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0x8d, I16X8ShrU, "i16x8.shr_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x8e, I16X8Add, "i16x8.add", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x8f, I16X8AddSatS, "i16x8.add_sat_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x90, I16X8AddSatU, "i16x8.add_sat_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x91, I16X8Sub, "i16x8.sub", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x92, I16X8SubSatS, "i16x8.sub_sat_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x93, I16X8SubSatU, "i16x8.sub_sat_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x95, I16X8Mul, "i16x8.mul", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x96, I16X8MinS, "i16x8.min_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x97, I16X8MinU, "i16x8.min_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x98, I16X8MaxS, "i16x8.max_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x99, I16X8MaxU, "i16x8.max_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x9b, I16X8AvgrU, "i16x8.avgr_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x9c, I16X8ExtmulLowI8X16S, "i16x8.extmul_low_i8x16_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x9d, I16X8ExtmulHighI8X16S, "i16x8.extmul_high_i8x16_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x9e, I16X8ExtmulLowI8X16U, "i16x8.extmul_low_i8x16_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x9f, I16X8ExtmulHighI8X16U, "i16x8.extmul_high_i8x16_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xa0, I32X4Abs, "i32x4.abs", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xa1, I32X4Neg, "i32x4.neg", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0xa3, I32X4AllTrue, "i32x4.all_true", "")
+WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0xa4, I32X4Bitmask, "i32x4.bitmask", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xa7, I32X4ExtendLowI16X8S, "i32x4.extend_low_i16x8_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xa8, I32X4ExtendHighI16X8S, "i32x4.extend_high_i16x8_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xa9, I32X4ExtendLowI16X8U, "i32x4.extend_low_i16x8_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xaa, I32X4ExtendHighI16X8U, "i32x4.extend_high_i16x8_u", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0xab, I32X4Shl, "i32x4.shl", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0xac, I32X4ShrS, "i32x4.shr_s", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0xad, I32X4ShrU, "i32x4.shr_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xae, I32X4Add, "i32x4.add", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xb1, I32X4Sub, "i32x4.sub", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xb5, I32X4Mul, "i32x4.mul", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xb6, I32X4MinS, "i32x4.min_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xb7, I32X4MinU, "i32x4.min_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xb8, I32X4MaxS, "i32x4.max_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xb9, I32X4MaxU, "i32x4.max_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xba, I32X4DotI16X8S, "i32x4.dot_i16x8_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xbc, I32X4ExtmulLowI16X8S, "i32x4.extmul_low_i16x8_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xbd, I32X4ExtmulHighI16X8S, "i32x4.extmul_high_i16x8_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xbe, I32X4ExtmulLowI16X8U, "i32x4.extmul_low_i16x8_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xbf, I32X4ExtmulHighI16X8U, "i32x4.extmul_high_i16x8_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xc0, I64X2Abs, "i64x2.abs", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xc1, I64X2Neg, "i64x2.neg", "")
+WABT_OPCODE( I32, V128, ___, ___, 0, 0xfd, 0xc3, I64X2AllTrue, "i64x2.all_true", "")
+WABT_OPCODE( I32, V128, ___, ___, 0, 0xfd, 0xc4, I64X2Bitmask, "i64x2.bitmask", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xc7, I64X2ExtendLowI32X4S, "i64x2.extend_low_i32x4_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xc8, I64X2ExtendHighI32X4S, "i64x2.extend_high_i32x4_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xc9, I64X2ExtendLowI32X4U, "i64x2.extend_low_i32x4_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xca, I64X2ExtendHighI32X4U, "i64x2.extend_high_i32x4_u", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0xcb, I64X2Shl, "i64x2.shl", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0xcc, I64X2ShrS, "i64x2.shr_s", "")
+WABT_OPCODE(V128, V128, I32, ___, 0, 0xfd, 0xcd, I64X2ShrU, "i64x2.shr_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xce, I64X2Add, "i64x2.add", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xd1, I64X2Sub, "i64x2.sub", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xd5, I64X2Mul, "i64x2.mul", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xd6, I64X2Eq, "i64x2.eq", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xd7, I64X2Ne, "i64x2.ne", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xd8, I64X2LtS, "i64x2.lt_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xd9, I64X2GtS, "i64x2.gt_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xda, I64X2LeS, "i64x2.le_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xdb, I64X2GeS, "i64x2.ge_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xdc, I64X2ExtmulLowI32X4S, "i64x2.extmul_low_i32x4_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xdd, I64X2ExtmulHighI32X4S, "i64x2.extmul_high_i32x4_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xde, I64X2ExtmulLowI32X4U, "i64x2.extmul_low_i32x4_u", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xdf, I64X2ExtmulHighI32X4U, "i64x2.extmul_high_i32x4_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x67, F32X4Ceil, "f32x4.ceil", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x68, F32X4Floor, "f32x4.floor", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x69, F32X4Trunc, "f32x4.trunc", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x6a, F32X4Nearest, "f32x4.nearest", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x74, F64X2Ceil, "f64x2.ceil", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x75, F64X2Floor, "f64x2.floor", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x7a, F64X2Trunc, "f64x2.trunc", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x94, F64X2Nearest, "f64x2.nearest", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xe0, F32X4Abs, "f32x4.abs", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xe1, F32X4Neg, "f32x4.neg", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xe3, F32X4Sqrt, "f32x4.sqrt", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xe4, F32X4Add, "f32x4.add", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xe5, F32X4Sub, "f32x4.sub", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xe6, F32X4Mul, "f32x4.mul", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xe7, F32X4Div, "f32x4.div", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xe8, F32X4Min, "f32x4.min", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xe9, F32X4Max, "f32x4.max", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xea, F32X4PMin, "f32x4.pmin", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xeb, F32X4PMax, "f32x4.pmax", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xec, F64X2Abs, "f64x2.abs", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xed, F64X2Neg, "f64x2.neg", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xef, F64X2Sqrt, "f64x2.sqrt", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xf0, F64X2Add, "f64x2.add", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xf1, F64X2Sub, "f64x2.sub", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xf2, F64X2Mul, "f64x2.mul", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xf3, F64X2Div, "f64x2.div", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xf4, F64X2Min, "f64x2.min", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xf5, F64X2Max, "f64x2.max", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xf6, F64X2PMin, "f64x2.pmin", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0xf7, F64X2PMax, "f64x2.pmax", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xf8, I32X4TruncSatF32X4S,"i32x4.trunc_sat_f32x4_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xf9, I32X4TruncSatF32X4U,"i32x4.trunc_sat_f32x4_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfa, F32X4ConvertI32X4S, "f32x4.convert_i32x4_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfb, F32X4ConvertI32X4U, "f32x4.convert_i32x4_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfc, I32X4TruncSatF64X2SZero, "i32x4.trunc_sat_f64x2_s_zero", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfd, I32X4TruncSatF64X2UZero, "i32x4.trunc_sat_f64x2_u_zero", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xfe, F64X2ConvertLowI32X4S, "f64x2.convert_low_i32x4_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0xff, F64X2ConvertLowI32X4U, "f64x2.convert_low_i32x4_u", "")
+
+/* Relaxed-SIMD opcodes */
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x100, I8X16RelaxedSwizzle, "i8x16.relaxed_swizzle", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x101, I32X4RelaxedTruncF32X4S, "i32x4.relaxed_trunc_f32x4_s", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x102, I32X4RelaxedTruncF32X4U, "i32x4.relaxed_trunc_f32x4_u", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x103, I32X4RelaxedTruncF64X2SZero, "i32x4.relaxed_trunc_f64x2_s_zero", "")
+WABT_OPCODE(V128, V128, ___, ___, 0, 0xfd, 0x104, I32X4RelaxedTruncF64X2UZero, "i32x4.relaxed_trunc_f64x2_u_zero", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x105, F32X4RelaxedMadd, "f32x4.relaxed_madd", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x106, F32X4RelaxedNmadd, "f32x4.relaxed_nmadd", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x107, F64X2RelaxedMadd, "f64x2.relaxed_madd", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x108, F64X2RelaxedNmadd, "f64x2.relaxed_nmadd", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x109, I8X16RelaxedLaneSelect, "i8x16.relaxed_laneselect", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10a, I16X8RelaxedLaneSelect, "i16x8.relaxed_laneselect", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10b, I32X4RelaxedLaneSelect, "i32x4.relaxed_laneselect", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x10c, I64X2RelaxedLaneSelect, "i64x2.relaxed_laneselect", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10d, F32X4RelaxedMin, "f32x4.relaxed_min", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10e, F32X4RelaxedMax, "f32x4.relaxed_max", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x10f, F64X2RelaxedMin, "f64x2.relaxed_min", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x110, F64X2RelaxedMax, "f64x2.relaxed_max", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x111, I16X8RelaxedQ15mulrS, "i16x8.relaxed_q15mulr_s", "")
+WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x112, I16X8DotI8X16I7X16S, "i16x8.dot_i8x16_i7x16_s", "")
+WABT_OPCODE(V128, V128, V128, V128, 0, 0xfd, 0x113, I32X4DotI8X16I7X16AddS, "i32x4.dot_i8x16_i7x16_add_s", "")
+
+/* Thread opcodes (--enable-threads) */
+WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x00, MemoryAtomicNotify, "memory.atomic.notify", "")
+WABT_OPCODE(I32, I32, I32, I64, 4, 0xfe, 0x01, MemoryAtomicWait32, "memory.atomic.wait32", "")
+WABT_OPCODE(I32, I32, I64, I64, 8, 0xfe, 0x02, MemoryAtomicWait64, "memory.atomic.wait64", "")
+WABT_OPCODE(___, ___, ___, ___, 0, 0xfe, 0x03, AtomicFence, "atomic.fence", "")
+WABT_OPCODE(I32, I32, ___, ___, 4, 0xfe, 0x10, I32AtomicLoad, "i32.atomic.load", "")
+WABT_OPCODE(I64, I32, ___, ___, 8, 0xfe, 0x11, I64AtomicLoad, "i64.atomic.load", "")
+WABT_OPCODE(I32, I32, ___, ___, 1, 0xfe, 0x12, I32AtomicLoad8U, "i32.atomic.load8_u", "")
+WABT_OPCODE(I32, I32, ___, ___, 2, 0xfe, 0x13, I32AtomicLoad16U, "i32.atomic.load16_u", "")
+WABT_OPCODE(I64, I32, ___, ___, 1, 0xfe, 0x14, I64AtomicLoad8U, "i64.atomic.load8_u", "")
+WABT_OPCODE(I64, I32, ___, ___, 2, 0xfe, 0x15, I64AtomicLoad16U, "i64.atomic.load16_u", "")
+WABT_OPCODE(I64, I32, ___, ___, 4, 0xfe, 0x16, I64AtomicLoad32U, "i64.atomic.load32_u", "")
+WABT_OPCODE(___, I32, I32, ___, 4, 0xfe, 0x17, I32AtomicStore, "i32.atomic.store", "")
+WABT_OPCODE(___, I32, I64, ___, 8, 0xfe, 0x18, I64AtomicStore, "i64.atomic.store", "")
+WABT_OPCODE(___, I32, I32, ___, 1, 0xfe, 0x19, I32AtomicStore8, "i32.atomic.store8", "")
+WABT_OPCODE(___, I32, I32, ___, 2, 0xfe, 0x1a, I32AtomicStore16, "i32.atomic.store16", "")
+WABT_OPCODE(___, I32, I64, ___, 1, 0xfe, 0x1b, I64AtomicStore8, "i64.atomic.store8", "")
+WABT_OPCODE(___, I32, I64, ___, 2, 0xfe, 0x1c, I64AtomicStore16, "i64.atomic.store16", "")
+WABT_OPCODE(___, I32, I64, ___, 4, 0xfe, 0x1d, I64AtomicStore32, "i64.atomic.store32", "")
+WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x1e, I32AtomicRmwAdd, "i32.atomic.rmw.add", "")
+WABT_OPCODE(I64, I32, I64, ___, 8, 0xfe, 0x1f, I64AtomicRmwAdd, "i64.atomic.rmw.add", "")
+WABT_OPCODE(I32, I32, I32, ___, 1, 0xfe, 0x20, I32AtomicRmw8AddU, "i32.atomic.rmw8.add_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 2, 0xfe, 0x21, I32AtomicRmw16AddU, "i32.atomic.rmw16.add_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 1, 0xfe, 0x22, I64AtomicRmw8AddU, "i64.atomic.rmw8.add_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 2, 0xfe, 0x23, I64AtomicRmw16AddU, "i64.atomic.rmw16.add_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 4, 0xfe, 0x24, I64AtomicRmw32AddU, "i64.atomic.rmw32.add_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x25, I32AtomicRmwSub, "i32.atomic.rmw.sub", "")
+WABT_OPCODE(I64, I32, I64, ___, 8, 0xfe, 0x26, I64AtomicRmwSub, "i64.atomic.rmw.sub", "")
+WABT_OPCODE(I32, I32, I32, ___, 1, 0xfe, 0x27, I32AtomicRmw8SubU, "i32.atomic.rmw8.sub_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 2, 0xfe, 0x28, I32AtomicRmw16SubU, "i32.atomic.rmw16.sub_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 1, 0xfe, 0x29, I64AtomicRmw8SubU, "i64.atomic.rmw8.sub_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 2, 0xfe, 0x2a, I64AtomicRmw16SubU, "i64.atomic.rmw16.sub_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 4, 0xfe, 0x2b, I64AtomicRmw32SubU, "i64.atomic.rmw32.sub_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x2c, I32AtomicRmwAnd, "i32.atomic.rmw.and", "")
+WABT_OPCODE(I64, I32, I64, ___, 8, 0xfe, 0x2d, I64AtomicRmwAnd, "i64.atomic.rmw.and", "")
+WABT_OPCODE(I32, I32, I32, ___, 1, 0xfe, 0x2e, I32AtomicRmw8AndU, "i32.atomic.rmw8.and_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 2, 0xfe, 0x2f, I32AtomicRmw16AndU, "i32.atomic.rmw16.and_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 1, 0xfe, 0x30, I64AtomicRmw8AndU, "i64.atomic.rmw8.and_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 2, 0xfe, 0x31, I64AtomicRmw16AndU, "i64.atomic.rmw16.and_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 4, 0xfe, 0x32, I64AtomicRmw32AndU, "i64.atomic.rmw32.and_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x33, I32AtomicRmwOr, "i32.atomic.rmw.or", "")
+WABT_OPCODE(I64, I32, I64, ___, 8, 0xfe, 0x34, I64AtomicRmwOr, "i64.atomic.rmw.or", "")
+WABT_OPCODE(I32, I32, I32, ___, 1, 0xfe, 0x35, I32AtomicRmw8OrU, "i32.atomic.rmw8.or_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 2, 0xfe, 0x36, I32AtomicRmw16OrU, "i32.atomic.rmw16.or_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 1, 0xfe, 0x37, I64AtomicRmw8OrU, "i64.atomic.rmw8.or_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 2, 0xfe, 0x38, I64AtomicRmw16OrU, "i64.atomic.rmw16.or_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 4, 0xfe, 0x39, I64AtomicRmw32OrU, "i64.atomic.rmw32.or_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x3a, I32AtomicRmwXor, "i32.atomic.rmw.xor", "")
+WABT_OPCODE(I64, I32, I64, ___, 8, 0xfe, 0x3b, I64AtomicRmwXor, "i64.atomic.rmw.xor", "")
+WABT_OPCODE(I32, I32, I32, ___, 1, 0xfe, 0x3c, I32AtomicRmw8XorU, "i32.atomic.rmw8.xor_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 2, 0xfe, 0x3d, I32AtomicRmw16XorU, "i32.atomic.rmw16.xor_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 1, 0xfe, 0x3e, I64AtomicRmw8XorU, "i64.atomic.rmw8.xor_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 2, 0xfe, 0x3f, I64AtomicRmw16XorU, "i64.atomic.rmw16.xor_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 4, 0xfe, 0x40, I64AtomicRmw32XorU, "i64.atomic.rmw32.xor_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 4, 0xfe, 0x41, I32AtomicRmwXchg, "i32.atomic.rmw.xchg", "")
+WABT_OPCODE(I64, I32, I64, ___, 8, 0xfe, 0x42, I64AtomicRmwXchg, "i64.atomic.rmw.xchg", "")
+WABT_OPCODE(I32, I32, I32, ___, 1, 0xfe, 0x43, I32AtomicRmw8XchgU, "i32.atomic.rmw8.xchg_u", "")
+WABT_OPCODE(I32, I32, I32, ___, 2, 0xfe, 0x44, I32AtomicRmw16XchgU, "i32.atomic.rmw16.xchg_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 1, 0xfe, 0x45, I64AtomicRmw8XchgU, "i64.atomic.rmw8.xchg_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 2, 0xfe, 0x46, I64AtomicRmw16XchgU, "i64.atomic.rmw16.xchg_u", "")
+WABT_OPCODE(I64, I32, I64, ___, 4, 0xfe, 0x47, I64AtomicRmw32XchgU, "i64.atomic.rmw32.xchg_u", "")
+WABT_OPCODE(I32, I32, I32, I32, 4, 0xfe, 0x48, I32AtomicRmwCmpxchg, "i32.atomic.rmw.cmpxchg", "")
+WABT_OPCODE(I64, I32, I64, I64, 8, 0xfe, 0x49, I64AtomicRmwCmpxchg, "i64.atomic.rmw.cmpxchg", "")
+WABT_OPCODE(I32, I32, I32, I32, 1, 0xfe, 0x4a, I32AtomicRmw8CmpxchgU, "i32.atomic.rmw8.cmpxchg_u", "")
+WABT_OPCODE(I32, I32, I32, I32, 2, 0xfe, 0x4b, I32AtomicRmw16CmpxchgU, "i32.atomic.rmw16.cmpxchg_u", "")
+WABT_OPCODE(I64, I32, I64, I64, 1, 0xfe, 0x4c, I64AtomicRmw8CmpxchgU, "i64.atomic.rmw8.cmpxchg_u", "")
+WABT_OPCODE(I64, I32, I64, I64, 2, 0xfe, 0x4d, I64AtomicRmw16CmpxchgU, "i64.atomic.rmw16.cmpxchg_u", "")
+WABT_OPCODE(I64, I32, I64, I64, 4, 0xfe, 0x4e, I64AtomicRmw32CmpxchgU, "i64.atomic.rmw32.cmpxchg_u", "")
diff --git a/third_party/wasm2c/include/wabt/opcode.h b/third_party/wasm2c/include/wabt/opcode.h
new file mode 100644
index 0000000000..a7c7b2495a
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/opcode.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_OPCODE_H_
+#define WABT_OPCODE_H_
+
+#include <vector>
+
+#include "wabt/common.h"
+#include "wabt/leb128.h"
+#include "wabt/opcode-code-table.h"
+
+namespace wabt {
+
+class Features;
+
+struct Opcode {
+ // Opcode enumerations.
+ //
+ // NOTE: this enum does not match the binary encoding.
+ //
+ enum Enum : uint32_t {
+#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
+ text, decomp) \
+ Name,
+#include "wabt/opcode.def"
+#undef WABT_OPCODE
+ Invalid,
+ };
+
+// Static opcode objects.
+#define WABT_OPCODE(rtype, type1, type2, type3, mem_size, prefix, code, Name, \
+ text, decomp) \
+ static Opcode Name##_Opcode;
+#include "wabt/opcode.def"
+#undef WABT_OPCODE
+
+ Opcode() = default; // Provided so Opcode can be member of a union.
+ Opcode(Enum e) : enum_(e) {}
+ operator Enum() const { return enum_; }
+
+ static Opcode FromCode(uint32_t);
+ static Opcode FromCode(uint8_t prefix, uint32_t code);
+ bool HasPrefix() const { return GetInfo().prefix != 0; }
+ uint8_t GetPrefix() const { return GetInfo().prefix; }
+ uint32_t GetCode() const { return GetInfo().code; }
+ size_t GetLength() const { return GetBytes().size(); }
+ const char* GetName() const { return GetInfo().name; }
+ const char* GetDecomp() const {
+ return *GetInfo().decomp ? GetInfo().decomp : GetInfo().name;
+ }
+ Type GetResultType() const { return GetInfo().result_type; }
+ Type GetParamType1() const { return GetInfo().param_types[0]; }
+ Type GetParamType2() const { return GetInfo().param_types[1]; }
+ Type GetParamType3() const { return GetInfo().param_types[2]; }
+ Type GetParamType(int n) const { return GetInfo().param_types[n - 1]; }
+ Address GetMemorySize() const { return GetInfo().memory_size; }
+
+ // Get the byte sequence for this opcode, including prefix.
+ std::vector<uint8_t> GetBytes() const;
+
+ // Get the lane count of an extract/replace simd op.
+ uint32_t GetSimdLaneCount() const;
+
+ // Return 1 if |alignment| matches the alignment of |opcode|, or if
+ // |alignment| is WABT_USE_NATURAL_ALIGNMENT.
+ bool IsNaturallyAligned(Address alignment) const;
+
+ // If |alignment| is WABT_USE_NATURAL_ALIGNMENT, return the alignment of
+ // |opcode|, else return |alignment|.
+ Address GetAlignment(Address alignment) const;
+
+ static bool IsPrefixByte(uint8_t byte) {
+ return byte == kMathPrefix || byte == kThreadsPrefix || byte == kSimdPrefix;
+ }
+
+ bool IsEnabled(const Features& features) const;
+ bool IsInvalid() const { return enum_ >= Invalid; }
+
+ private:
+ static constexpr uint32_t kMathPrefix = 0xfc;
+ static constexpr uint32_t kThreadsPrefix = 0xfe;
+ static constexpr uint32_t kSimdPrefix = 0xfd;
+
+ struct Info {
+ const char* name;
+ const char* decomp;
+ Type result_type;
+ Type param_types[3];
+ Address memory_size;
+ uint8_t prefix;
+ uint32_t code;
+ uint32_t prefix_code; // See PrefixCode below. Used for fast lookup.
+ };
+
+ static uint32_t PrefixCode(uint8_t prefix, uint32_t code) {
+ if (code >= (1 << MAX_OPCODE_BITS)) {
+ // Clamp to (2^bits - 1), since we know that it is an invalid code.
+ code = (1 << MAX_OPCODE_BITS) - 1;
+ }
+ return (prefix << MAX_OPCODE_BITS) | code;
+ }
+
+ // The Opcode struct only stores an enumeration (Opcode::Enum) of all valid
+ // opcodes, densely packed. We want to be able to store invalid opcodes as
+ // well, for display to the user. To encode these, we use PrefixCode() to
+ // generate a uint32_t of the prefix/code pair, then negate the value so it
+ // doesn't overlap with the valid enum values. The negation is done using
+ // `~code + 1` since prefix_code is unsigned, and MSVC warns if you use - on
+ // an unsigned value.
+ //
+ // | 0 | Opcode::Invalid | INT32_MAX+1 UINT32_MAX |
+ // |---------------|-------------------------|---------------------------|
+ // | valid opcodes | unused space | invalid opcodes |
+ //
+ static Enum EncodeInvalidOpcode(uint32_t prefix_code) {
+ Enum result = static_cast<Enum>(~prefix_code + 1);
+ assert(result >= Invalid);
+ return result;
+ }
+
+ static void DecodeInvalidOpcode(Enum e,
+ uint8_t* out_prefix,
+ uint32_t* out_code) {
+ uint32_t prefix_code = ~static_cast<uint32_t>(e) + 1;
+ *out_prefix = prefix_code >> MAX_OPCODE_BITS;
+ *out_code = prefix_code & 0xff;
+ }
+
+ Info GetInfo() const;
+ static Info infos_[];
+
+ Enum enum_;
+};
+
+// static
+inline Opcode Opcode::FromCode(uint32_t code) {
+ return FromCode(0, code);
+}
+
+// static
+inline Opcode Opcode::FromCode(uint8_t prefix, uint32_t code) {
+ uint32_t prefix_code = PrefixCode(prefix, code);
+
+ if (WABT_LIKELY(prefix_code < WABT_ARRAY_SIZE(WabtOpcodeCodeTable))) {
+ uint32_t value = WabtOpcodeCodeTable[prefix_code];
+ // The default value in the table is 0. That's a valid value, but only if
+ // the code is 0 (for nop).
+ if (WABT_LIKELY(value != 0 || code == 0)) {
+ return Opcode(static_cast<Enum>(value));
+ }
+ }
+
+ return Opcode(EncodeInvalidOpcode(prefix_code));
+}
+
+} // namespace wabt
+
+#endif // WABT_OPCODE_H_
diff --git a/third_party/wasm2c/include/wabt/option-parser.h b/third_party/wasm2c/include/wabt/option-parser.h
new file mode 100644
index 0000000000..0203ce0ccd
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/option-parser.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_OPTION_PARSER_H_
+#define WABT_OPTION_PARSER_H_
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+class OptionParser {
+ public:
+ enum class HasArgument { No, Yes };
+ enum class ArgumentCount { One, OneOrMore, ZeroOrMore };
+
+ struct Option;
+ using Callback = std::function<void(const char*)>;
+ using NullCallback = std::function<void()>;
+
+ struct Option {
+ Option(char short_name,
+ const std::string& long_name,
+ const std::string& metavar,
+ HasArgument has_argument,
+ const std::string& help,
+ const Callback&);
+
+ char short_name;
+ std::string long_name;
+ std::string metavar;
+ bool has_argument;
+ std::string help;
+ Callback callback;
+ };
+
+ struct Argument {
+ Argument(const std::string& name, ArgumentCount, const Callback&);
+
+ std::string name;
+ ArgumentCount count;
+ Callback callback;
+ int handled_count = 0;
+ };
+
+ explicit OptionParser(const char* program_name, const char* description);
+
+ void AddOption(const Option&);
+ void AddArgument(const std::string& name, ArgumentCount, const Callback&);
+ void SetErrorCallback(const Callback&);
+ void Parse(int argc, char* argv[]);
+ void PrintHelp();
+
+ // Helper functions.
+ void AddOption(char short_name,
+ const char* long_name,
+ const char* help,
+ const NullCallback&);
+ void AddOption(const char* long_name, const char* help, const NullCallback&);
+ void AddOption(char short_name,
+ const char* long_name,
+ const char* metavar,
+ const char* help,
+ const Callback&);
+
+ private:
+ static int Match(const char* s, const std::string& full, bool has_argument);
+ void WABT_PRINTF_FORMAT(2, 3) Errorf(const char* format, ...);
+ void HandleArgument(size_t* arg_index, const char* arg_value);
+
+ // Print the error and exit(1).
+ void DefaultError(const std::string&);
+
+ std::string program_name_;
+ std::string description_;
+ std::vector<Option> options_;
+ std::vector<Argument> arguments_;
+ Callback on_error_;
+};
+
+} // namespace wabt
+
+#endif /* WABT_OPTION_PARSER_H_ */
diff --git a/third_party/wasm2c/include/wabt/range.h b/third_party/wasm2c/include/wabt/range.h
new file mode 100644
index 0000000000..15202e1ed3
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/range.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_RANGE_H_
+#define WABT_RANGE_H_
+
+namespace wabt {
+
+template <typename T>
+struct Range {
+ Range() : start(0), end(0) {}
+ Range(T start, T end) : start(start), end(end) {}
+ T start;
+ T end;
+
+ T size() const { return end - start; }
+};
+
+using OffsetRange = Range<Offset>;
+using ColumnRange = Range<int>;
+
+} // namespace wabt
+
+#endif // WABT_RANGE_H_
diff --git a/third_party/wasm2c/include/wabt/resolve-names.h b/third_party/wasm2c/include/wabt/resolve-names.h
new file mode 100644
index 0000000000..17ba1eedc5
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/resolve-names.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_RESOLVE_NAMES_H_
+#define WABT_RESOLVE_NAMES_H_
+
+#include "wabt/common.h"
+#include "wabt/error.h"
+
+namespace wabt {
+
+struct Module;
+struct Script;
+
+Result ResolveNamesModule(Module*, Errors*);
+Result ResolveNamesScript(Script*, Errors*);
+
+} // namespace wabt
+
+#endif /* WABT_RESOLVE_NAMES_H_ */
diff --git a/third_party/wasm2c/include/wabt/result.h b/third_party/wasm2c/include/wabt/result.h
new file mode 100644
index 0000000000..a40faab78b
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/result.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_RESULT_H_
+#define WABT_RESULT_H_
+
+namespace wabt {
+
+struct Result {
+ enum Enum {
+ Ok,
+ Error,
+ };
+
+ Result() : Result(Ok) {}
+ Result(Enum e) : enum_(e) {}
+ operator Enum() const { return enum_; }
+ Result& operator|=(Result rhs);
+
+ private:
+ Enum enum_;
+};
+
+inline Result operator|(Result lhs, Result rhs) {
+ return (lhs == Result::Error || rhs == Result::Error) ? Result::Error
+ : Result::Ok;
+}
+
+inline Result& Result::operator|=(Result rhs) {
+ enum_ = *this | rhs;
+ return *this;
+}
+
+inline bool Succeeded(Result result) {
+ return result == Result::Ok;
+}
+inline bool Failed(Result result) {
+ return result == Result::Error;
+}
+
+#define CHECK_RESULT(expr) \
+ do { \
+ if (Failed(expr)) { \
+ return ::wabt::Result::Error; \
+ } \
+ } while (0)
+
+} // namespace wabt
+
+#endif // WABT_RESULT_H_
diff --git a/third_party/wasm2c/include/wabt/sha256.h b/third_party/wasm2c/include/wabt/sha256.h
new file mode 100644
index 0000000000..744e2d1c63
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/sha256.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_SHA256_H_
+#define WABT_SHA256_H_
+
+#include "wabt/config.h"
+
+#include <string>
+#include <string_view>
+
+namespace wabt {
+
+void sha256(std::string_view input, std::string& digest);
+
+} // namespace wabt
+
+#endif // WABT_SHA256_H_
diff --git a/third_party/wasm2c/include/wabt/shared-validator.h b/third_party/wasm2c/include/wabt/shared-validator.h
new file mode 100644
index 0000000000..8c1f3988b1
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/shared-validator.h
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#ifndef WABT_SHARED_VALIDATOR_H_
+#define WABT_SHARED_VALIDATOR_H_
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include "wabt/common.h"
+#include "wabt/error.h"
+#include "wabt/feature.h"
+#include "wabt/ir.h"
+#include "wabt/opcode.h"
+#include "wabt/type-checker.h"
+
+#include "wabt/binary-reader.h" // For TypeMut.
+
+namespace wabt {
+
+struct ValidateOptions {
+ ValidateOptions() = default;
+ ValidateOptions(const Features& features) : features(features) {}
+
+ Features features;
+};
+
+class SharedValidator {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(SharedValidator);
+ SharedValidator(Errors*, const ValidateOptions& options);
+
+ // TODO: Move into SharedValidator?
+ using Label = TypeChecker::Label;
+ size_t type_stack_size() const { return typechecker_.type_stack_size(); }
+ Result GetLabel(Index depth, Label** out_label) {
+ return typechecker_.GetLabel(depth, out_label);
+ }
+ Result GetCatchCount(Index depth, Index* out_count) {
+ return typechecker_.GetCatchCount(depth, out_count);
+ }
+
+ Result WABT_PRINTF_FORMAT(3, 4)
+ PrintError(const Location& loc, const char* fmt, ...);
+
+ void OnTypecheckerError(const char* msg);
+
+ Index GetLocalCount() const;
+
+ Result EndModule();
+
+ Result OnFuncType(const Location&,
+ Index param_count,
+ const Type* param_types,
+ Index result_count,
+ const Type* result_types,
+ Index type_index);
+ Result OnStructType(const Location&, Index field_count, TypeMut* fields);
+ Result OnArrayType(const Location&, TypeMut field);
+
+ Result OnFunction(const Location&, Var sig_var);
+ Result OnTable(const Location&, Type elem_type, const Limits&);
+ Result OnMemory(const Location&, const Limits&);
+ Result OnGlobalImport(const Location&, Type type, bool mutable_);
+ Result OnGlobal(const Location&, Type type, bool mutable_);
+ Result OnTag(const Location&, Var sig_var);
+
+ Result OnExport(const Location&,
+ ExternalKind,
+ Var item_var,
+ std::string_view name);
+
+ Result OnStart(const Location&, Var func_var);
+
+ Result OnElemSegment(const Location&, Var table_var, SegmentKind);
+ Result OnElemSegmentElemType(const Location&, Type elem_type);
+ Result OnElemSegmentElemExpr_RefNull(const Location&, Type type);
+ Result OnElemSegmentElemExpr_RefFunc(const Location&, Var func_var);
+ Result OnElemSegmentElemExpr_Other(const Location&);
+
+ void OnDataCount(Index count);
+ Result OnDataSegment(const Location&, Var memory_var, SegmentKind);
+
+ Result BeginInitExpr(const Location&, Type type);
+ Result EndInitExpr();
+
+ Result BeginFunctionBody(const Location&, Index func_index);
+ Result EndFunctionBody(const Location&);
+ Result OnLocalDecl(const Location&, Index count, Type type);
+
+ Result OnAtomicFence(const Location&, uint32_t consistency_model);
+ Result OnAtomicLoad(const Location&, Opcode, Var memidx, Address align);
+ Result OnAtomicNotify(const Location&, Opcode, Var memidx, Address align);
+ Result OnAtomicRmwCmpxchg(const Location&, Opcode, Var memidx, Address align);
+ Result OnAtomicRmw(const Location&, Opcode, Var memidx, Address align);
+ Result OnAtomicStore(const Location&, Opcode, Var memidx, Address align);
+ Result OnAtomicWait(const Location&, Opcode, Var memidx, Address align);
+ Result OnBinary(const Location&, Opcode);
+ Result OnBlock(const Location&, Type sig_type);
+ Result OnBr(const Location&, Var depth);
+ Result OnBrIf(const Location&, Var depth);
+ Result BeginBrTable(const Location&);
+ Result OnBrTableTarget(const Location&, Var depth);
+ Result EndBrTable(const Location&);
+ Result OnCall(const Location&, Var func_var);
+ Result OnCallIndirect(const Location&, Var sig_var, Var table_var);
+ Result OnCallRef(const Location&, Index* function_type_index);
+ Result OnCatch(const Location&, Var tag_var, bool is_catch_all);
+ Result OnCompare(const Location&, Opcode);
+ Result OnConst(const Location&, Type);
+ Result OnConvert(const Location&, Opcode);
+ Result OnDataDrop(const Location&, Var segment_var);
+ Result OnDelegate(const Location&, Var depth);
+ Result OnDrop(const Location&);
+ Result OnElemDrop(const Location&, Var segment_var);
+ Result OnElse(const Location&);
+ Result OnEnd(const Location&);
+ Result OnGlobalGet(const Location&, Var);
+ Result OnGlobalSet(const Location&, Var);
+ Result OnIf(const Location&, Type sig_type);
+ Result OnLoad(const Location&, Opcode, Var memidx, Address align);
+ Result OnLoadSplat(const Location&, Opcode, Var memidx, Address align);
+ Result OnLoadZero(const Location&, Opcode, Var memidx, Address align);
+ Result OnLocalGet(const Location&, Var);
+ Result OnLocalSet(const Location&, Var);
+ Result OnLocalTee(const Location&, Var);
+ Result OnLoop(const Location&, Type sig_type);
+ Result OnMemoryCopy(const Location&, Var srcmemidx, Var destmemidx);
+ Result OnMemoryFill(const Location&, Var memidx);
+ Result OnMemoryGrow(const Location&, Var memidx);
+ Result OnMemoryInit(const Location&, Var segment_var, Var memidx);
+ Result OnMemorySize(const Location&, Var memidx);
+ Result OnNop(const Location&);
+ Result OnRefFunc(const Location&, Var func_var);
+ Result OnRefIsNull(const Location&);
+ Result OnRefNull(const Location&, Type type);
+ Result OnRethrow(const Location&, Var depth);
+ Result OnReturnCall(const Location&, Var func_var);
+ Result OnReturnCallIndirect(const Location&, Var sig_var, Var table_var);
+ Result OnReturn(const Location&);
+ Result OnSelect(const Location&, Index result_count, Type* result_types);
+ Result OnSimdLaneOp(const Location&, Opcode, uint64_t lane_idx);
+ Result OnSimdLoadLane(const Location&,
+ Opcode,
+ Var memidx,
+ Address align,
+ uint64_t lane_idx);
+ Result OnSimdStoreLane(const Location&,
+ Opcode,
+ Var memidx,
+ Address align,
+ uint64_t lane_idx);
+ Result OnSimdShuffleOp(const Location&, Opcode, v128 lane_idx);
+ Result OnStore(const Location&, Opcode, Var memidx, Address align);
+ Result OnTableCopy(const Location&, Var dst_var, Var src_var);
+ Result OnTableFill(const Location&, Var table_var);
+ Result OnTableGet(const Location&, Var table_var);
+ Result OnTableGrow(const Location&, Var table_var);
+ Result OnTableInit(const Location&, Var segment_var, Var table_var);
+ Result OnTableSet(const Location&, Var table_var);
+ Result OnTableSize(const Location&, Var table_var);
+ Result OnTernary(const Location&, Opcode);
+ Result OnThrow(const Location&, Var tag_var);
+ Result OnTry(const Location&, Type sig_type);
+ Result OnUnary(const Location&, Opcode);
+ Result OnUnreachable(const Location&);
+
+ private:
+ struct FuncType {
+ FuncType() = default;
+ FuncType(const TypeVector& params,
+ const TypeVector& results,
+ Index type_index)
+ : params(params), results(results), type_index(type_index) {}
+
+ TypeVector params;
+ TypeVector results;
+ Index type_index;
+ };
+
+ struct StructType {
+ StructType() = default;
+ StructType(const TypeMutVector& fields) : fields(fields) {}
+
+ TypeMutVector fields;
+ };
+
+ struct ArrayType {
+ ArrayType() = default;
+ ArrayType(TypeMut field) : field(field) {}
+
+ TypeMut field;
+ };
+
+ struct TableType {
+ TableType() = default;
+ TableType(Type element, Limits limits) : element(element), limits(limits) {}
+
+ Type element = Type::Any;
+ Limits limits;
+ };
+
+ struct MemoryType {
+ MemoryType() = default;
+ MemoryType(Limits limits) : limits(limits) {}
+
+ Limits limits;
+ };
+
+ struct GlobalType {
+ GlobalType() = default;
+ GlobalType(Type type, bool mutable_) : type(type), mutable_(mutable_) {}
+
+ Type type = Type::Any;
+ bool mutable_ = true;
+ };
+
+ struct TagType {
+ TypeVector params;
+ };
+
+ struct ElemType {
+ ElemType() = default;
+ ElemType(Type element, bool is_active, Type table_type)
+ : element(element), is_active(is_active), table_type(table_type) {}
+
+ Type element;
+ bool is_active;
+ Type table_type;
+ };
+
+ struct LocalDecl {
+ Type type;
+ Index end;
+ };
+
+ bool ValidInitOpcode(Opcode opcode) const;
+ Result CheckInstr(Opcode opcode, const Location& loc);
+ Result CheckType(const Location&,
+ Type actual,
+ Type expected,
+ const char* desc);
+ Result CheckLimits(const Location&,
+ const Limits&,
+ uint64_t absolute_max,
+ const char* desc);
+
+ Result CheckLocalIndex(Var local_var, Type* out_type);
+
+ Result CheckDeclaredFunc(Var func_var);
+
+ Result CheckIndex(Var var, Index max_index, const char* desc);
+ template <typename T>
+ Result CheckIndexWithValue(Var var,
+ const std::vector<T>& values,
+ T* out,
+ const char* desc);
+ Result CheckFuncTypeIndex(Var sig_var, FuncType* out = nullptr);
+ Result CheckFuncIndex(Var func_var, FuncType* out = nullptr);
+ Result CheckTableIndex(Var table_var, TableType* out = nullptr);
+ Result CheckMemoryIndex(Var memory_var, MemoryType* out = nullptr);
+ Result CheckGlobalIndex(Var global_var, GlobalType* out = nullptr);
+ Result CheckTagIndex(Var tag_var, TagType* out = nullptr);
+ Result CheckElemSegmentIndex(Var elem_segment_var, ElemType* out = nullptr);
+ Result CheckDataSegmentIndex(Var data_segment_var);
+
+ Result CheckAlign(const Location&, Address align, Address natural_align);
+ Result CheckAtomicAlign(const Location&,
+ Address align,
+ Address natural_align);
+
+ Result CheckBlockSignature(const Location&,
+ Opcode,
+ Type sig_type,
+ TypeVector* out_param_types,
+ TypeVector* out_result_types);
+
+ Index GetFunctionTypeIndex(Index func_index) const;
+
+ TypeVector ToTypeVector(Index count, const Type* types);
+
+ ValidateOptions options_;
+ Errors* errors_;
+ TypeChecker typechecker_; // TODO: Move into SharedValidator.
+ // Cached for access by OnTypecheckerError.
+ Location expr_loc_ = Location(kInvalidOffset);
+ bool in_init_expr_ = false;
+
+ Index num_types_ = 0;
+ std::map<Index, FuncType> func_types_;
+ std::map<Index, StructType> struct_types_;
+ std::map<Index, ArrayType> array_types_;
+
+ std::vector<FuncType> funcs_; // Includes imported and defined.
+ std::vector<TableType> tables_; // Includes imported and defined.
+ std::vector<MemoryType> memories_; // Includes imported and defined.
+ std::vector<GlobalType> globals_; // Includes imported and defined.
+ std::vector<TagType> tags_; // Includes imported and defined.
+ std::vector<ElemType> elems_;
+ Index starts_ = 0;
+ Index num_imported_globals_ = 0;
+ Index data_segments_ = 0;
+
+ // Includes parameters, since this is only used for validating
+ // local.{get,set,tee} instructions.
+ std::vector<LocalDecl> locals_;
+
+ std::set<std::string> export_names_; // Used to check for duplicates.
+ std::set<Index> declared_funcs_; // TODO: optimize?
+ std::vector<Var> check_declared_funcs_;
+};
+
+} // namespace wabt
+
+#endif // WABT_SHARED_VALIDATOR_H_
diff --git a/third_party/wasm2c/include/wabt/stream.h b/third_party/wasm2c/include/wabt/stream.h
new file mode 100644
index 0000000000..67f50975eb
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/stream.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_STREAM_H_
+#define WABT_STREAM_H_
+
+#include <cassert>
+#include <memory>
+#include <vector>
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+/* whether to display the ASCII characters in the debug output for
+ * write_memory */
+enum class PrintChars {
+ No = 0,
+ Yes = 1,
+};
+
+class Stream {
+ public:
+ explicit Stream(Stream* log_stream = nullptr);
+ virtual ~Stream() = default;
+
+ size_t offset() { return offset_; }
+ Result result() { return result_; }
+
+ void set_log_stream(Stream* stream) {
+ assert(stream);
+ log_stream_ = stream;
+ }
+
+ Stream& log_stream() {
+ assert(log_stream_);
+ return *log_stream_;
+ }
+
+ bool has_log_stream() const { return log_stream_ != nullptr; }
+
+ void ClearOffset() { offset_ = 0; }
+ void AddOffset(ssize_t delta);
+
+ void WriteData(const void* src,
+ size_t size,
+ const char* desc = nullptr,
+ PrintChars = PrintChars::No);
+
+ template <typename T>
+ void WriteData(const std::vector<T> src,
+ const char* desc,
+ PrintChars print_chars = PrintChars::No) {
+ if (!src.empty()) {
+ WriteData(src.data(), src.size() * sizeof(T), desc, print_chars);
+ }
+ }
+
+ void WriteDataAt(size_t offset,
+ const void* src,
+ size_t size,
+ const char* desc = nullptr,
+ PrintChars = PrintChars::No);
+
+ void MoveData(size_t dst_offset, size_t src_offset, size_t size);
+
+ void Truncate(size_t size);
+
+ void WABT_PRINTF_FORMAT(2, 3) Writef(const char* format, ...);
+
+ // Specified as uint32_t instead of uint8_t so we can check if the value
+ // given is in range before wrapping.
+ void WriteU8(uint32_t value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ assert(value <= UINT8_MAX);
+ Write(static_cast<uint8_t>(value), desc, print_chars);
+ }
+ void WriteU32(uint32_t value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ Write(value, desc, print_chars);
+ }
+ void WriteU64(uint64_t value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ Write(value, desc, print_chars);
+ }
+ void WriteU128(v128 value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ Write(value, desc, print_chars);
+ }
+
+ void WriteChar(char c,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ WriteU8(static_cast<unsigned char>(c), desc, print_chars);
+ }
+
+ // Dump memory as text, similar to the xxd format.
+ void WriteMemoryDump(const void* start,
+ size_t size,
+ size_t offset = 0,
+ PrintChars print_chars = PrintChars::No,
+ const char* prefix = nullptr,
+ const char* desc = nullptr);
+
+ // Convenience functions for writing enums.
+ template <typename T>
+ void WriteU8Enum(T value,
+ const char* desc = nullptr,
+ PrintChars print_chars = PrintChars::No) {
+ WriteU8(static_cast<uint32_t>(value), desc, print_chars);
+ }
+
+ virtual void Flush() {}
+
+ protected:
+ virtual Result WriteDataImpl(size_t offset,
+ const void* data,
+ size_t size) = 0;
+ virtual Result MoveDataImpl(size_t dst_offset,
+ size_t src_offset,
+ size_t size) = 0;
+ virtual Result TruncateImpl(size_t size) = 0;
+
+ private:
+ template <typename T>
+ void Write(const T& data, const char* desc, PrintChars print_chars) {
+#if WABT_BIG_ENDIAN
+ char tmp[sizeof(T)];
+ memcpy(tmp, &data, sizeof(tmp));
+ SwapBytesSized(tmp, sizeof(tmp));
+ WriteData(tmp, sizeof(tmp), desc, print_chars);
+#else
+ WriteData(&data, sizeof(data), desc, print_chars);
+#endif
+ }
+
+ size_t offset_;
+ Result result_;
+ // Not owned. If non-null, log all writes to this stream.
+ Stream* log_stream_;
+};
+
+struct OutputBuffer {
+ Result WriteToFile(std::string_view filename) const;
+ Result WriteToStdout() const;
+
+ void clear() { data.clear(); }
+ size_t size() const { return data.size(); }
+
+ std::vector<uint8_t> data;
+};
+
+class MemoryStream : public Stream {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(MemoryStream);
+ MemoryStream(MemoryStream&&) = default;
+ explicit MemoryStream(Stream* log_stream = nullptr);
+ explicit MemoryStream(std::unique_ptr<OutputBuffer>&&,
+ Stream* log_stream = nullptr);
+
+ OutputBuffer& output_buffer() { return *buf_; }
+ std::unique_ptr<OutputBuffer> ReleaseOutputBuffer();
+
+ void Clear();
+
+ Result WriteToFile(std::string_view filename) {
+ return buf_->WriteToFile(filename);
+ }
+
+ protected:
+ Result WriteDataImpl(size_t offset, const void* data, size_t size) override;
+ Result MoveDataImpl(size_t dst_offset,
+ size_t src_offset,
+ size_t size) override;
+ Result TruncateImpl(size_t size) override;
+
+ private:
+ std::unique_ptr<OutputBuffer> buf_;
+};
+
+class FileStream : public Stream {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(FileStream);
+ explicit FileStream(std::string_view filename, Stream* log_stream = nullptr);
+ explicit FileStream(FILE*, Stream* log_stream = nullptr);
+ FileStream(FileStream&&);
+ FileStream& operator=(FileStream&&);
+ ~FileStream() override;
+
+ static std::unique_ptr<FileStream> CreateStdout();
+ static std::unique_ptr<FileStream> CreateStderr();
+
+ bool is_open() const { return file_ != nullptr; }
+
+ void Flush() override;
+
+ protected:
+ Result WriteDataImpl(size_t offset, const void* data, size_t size) override;
+ Result MoveDataImpl(size_t dst_offset,
+ size_t src_offset,
+ size_t size) override;
+ Result TruncateImpl(size_t size) override;
+
+ private:
+ FILE* file_;
+ size_t offset_;
+ bool should_close_;
+};
+
+} // namespace wabt
+
+#endif /* WABT_STREAM_H_ */
diff --git a/third_party/wasm2c/include/wabt/string-format.h b/third_party/wasm2c/include/wabt/string-format.h
new file mode 100644
index 0000000000..892facf27b
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/string-format.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2021 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.
+ */
+
+#ifndef WABT_STRING_FORMAT_H_
+#define WABT_STRING_FORMAT_H_
+
+#include <cstdarg>
+#include <string>
+#include <vector>
+
+#include "wabt/config.h"
+
+#define PRIstringview "%.*s"
+#define WABT_PRINTF_STRING_VIEW_ARG(x) \
+ static_cast<int>((x).length()), (x).data()
+
+#define PRItypecode "%s%#x"
+#define WABT_PRINTF_TYPE_CODE(x) \
+ (static_cast<int32_t>(x) < 0 ? "-" : ""), std::abs(static_cast<int32_t>(x))
+
+#define WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE 128
+#define WABT_SNPRINTF_ALLOCA(buffer, len, format) \
+ va_list args; \
+ va_list args_copy; \
+ va_start(args, format); \
+ va_copy(args_copy, args); \
+ char fixed_buf[WABT_DEFAULT_SNPRINTF_ALLOCA_BUFSIZE]; \
+ char* buffer = fixed_buf; \
+ size_t len = wabt_vsnprintf(fixed_buf, sizeof(fixed_buf), format, args); \
+ va_end(args); \
+ if (len + 1 > sizeof(fixed_buf)) { \
+ buffer = static_cast<char*>(alloca(len + 1)); \
+ len = wabt_vsnprintf(buffer, len + 1, format, args_copy); \
+ } \
+ va_end(args_copy)
+
+namespace wabt {
+
+inline std::string WABT_PRINTF_FORMAT(1, 2)
+ StringPrintf(const char* format, ...) {
+ va_list args;
+ va_list args_copy;
+ va_start(args, format);
+ va_copy(args_copy, args);
+ size_t len = wabt_vsnprintf(nullptr, 0, format, args) + 1; // For \0.
+ std::vector<char> buffer(len);
+ va_end(args);
+ wabt_vsnprintf(buffer.data(), len, format, args_copy);
+ va_end(args_copy);
+ return std::string(buffer.data(), len - 1);
+}
+
+} // namespace wabt
+
+#endif // WABT_STRING_FORMAT_H_
diff --git a/third_party/wasm2c/include/wabt/string-util.h b/third_party/wasm2c/include/wabt/string-util.h
new file mode 100644
index 0000000000..28734d504b
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/string-util.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_STRING_UTIL_H_
+#define WABT_STRING_UTIL_H_
+
+#include <string>
+#include <string_view>
+
+namespace wabt {
+
+inline std::string& operator+=(std::string& x, std::string_view y) {
+ x.append(y.data(), y.size());
+ return x;
+}
+
+inline std::string operator+(std::string_view x, std::string_view y) {
+ std::string s;
+ s.reserve(x.size() + y.size());
+ s.append(x.data(), x.size());
+ s.append(y.data(), y.size());
+ return s;
+}
+
+inline std::string operator+(const std::string& x, std::string_view y) {
+ return std::string_view(x) + y;
+}
+
+inline std::string operator+(std::string_view x, const std::string& y) {
+ return x + std::string_view(y);
+}
+
+inline std::string operator+(const char* x, std::string_view y) {
+ return std::string_view(x) + y;
+}
+
+inline std::string operator+(std::string_view x, const char* y) {
+ return x + std::string_view(y);
+}
+
+inline void cat_concatenate(std::string&) {}
+
+template <typename T, typename... Ts>
+void cat_concatenate(std::string& s, const T& t, const Ts&... args) {
+ s += t;
+ cat_concatenate(s, args...);
+}
+
+inline size_t cat_compute_size() {
+ return 0;
+}
+
+template <typename T, typename... Ts>
+size_t cat_compute_size(const T& t, const Ts&... args) {
+ return std::string_view(t).size() + cat_compute_size(args...);
+}
+
+// Is able to concatenate any combination of string/string_view/char*
+template <typename... Ts>
+std::string cat(const Ts&... args) {
+ std::string s;
+ s.reserve(cat_compute_size(args...));
+ cat_concatenate(s, args...);
+ return s;
+}
+
+} // namespace wabt
+
+#endif // WABT_STRING_UTIL_H_
diff --git a/third_party/wasm2c/include/wabt/token.def b/third_party/wasm2c/include/wabt/token.def
new file mode 100644
index 0000000000..1e95da62d1
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/token.def
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2018 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_TOKEN
+#error "You must define WABT_TOKEN before including this file."
+#endif
+
+/* Tokens with no additional data (i.e. bare). */
+WABT_TOKEN(Invalid, "Invalid")
+WABT_TOKEN(Array, "array")
+WABT_TOKEN(AssertException, "assert_exception")
+WABT_TOKEN(AssertExhaustion, "assert_exhaustion")
+WABT_TOKEN(AssertInvalid, "assert_invalid")
+WABT_TOKEN(AssertMalformed, "assert_malformed")
+WABT_TOKEN(AssertReturn, "assert_return")
+WABT_TOKEN(AssertTrap, "assert_trap")
+WABT_TOKEN(AssertUnlinkable, "assert_unlinkable")
+WABT_TOKEN(Bin, "bin")
+WABT_TOKEN(Item, "item")
+WABT_TOKEN(Data, "data")
+WABT_TOKEN(Declare, "declare")
+WABT_TOKEN(Delegate, "delegate")
+WABT_TOKEN(Do, "do")
+WABT_TOKEN(Either, "either")
+WABT_TOKEN(Elem, "elem")
+WABT_TOKEN(Eof, "EOF")
+WABT_TOKEN(Tag, "tag")
+WABT_TOKEN(Export, "export")
+WABT_TOKEN(Field, "field")
+WABT_TOKEN(Get, "get")
+WABT_TOKEN(Global, "global")
+WABT_TOKEN(Import, "import")
+WABT_TOKEN(Invoke, "invoke")
+WABT_TOKEN(Input, "input")
+WABT_TOKEN(Local, "local")
+WABT_TOKEN(Lpar, "(")
+WABT_TOKEN(Memory, "memory")
+WABT_TOKEN(Module, "module")
+WABT_TOKEN(Mut, "mut")
+WABT_TOKEN(NanArithmetic, "nan:arithmetic")
+WABT_TOKEN(NanCanonical, "nan:canonical")
+WABT_TOKEN(Offset, "offset")
+WABT_TOKEN(Output, "output")
+WABT_TOKEN(Param, "param")
+WABT_TOKEN(Ref, "ref")
+WABT_TOKEN(Quote, "quote")
+WABT_TOKEN(Register, "register")
+WABT_TOKEN(Result, "result")
+WABT_TOKEN(Rpar, ")")
+WABT_TOKEN(Shared, "shared")
+WABT_TOKEN(Start, "start")
+WABT_TOKEN(Struct, "struct")
+WABT_TOKEN(Table, "table")
+WABT_TOKEN(Then, "then")
+WABT_TOKEN(Type, "type")
+WABT_TOKEN(I8X16, "i8x16")
+WABT_TOKEN(I16X8, "i16x8")
+WABT_TOKEN(I32X4, "i32x4")
+WABT_TOKEN(I64X2, "i64x2")
+WABT_TOKEN(F32X4, "f32x4")
+WABT_TOKEN(F64X2, "f64x2")
+WABT_TOKEN_FIRST(Bare, Invalid)
+WABT_TOKEN_LAST(Bare, F64X2)
+
+/* Tokens with Literal data. */
+WABT_TOKEN(Float, "FLOAT")
+WABT_TOKEN(Int, "INT")
+WABT_TOKEN(Nat, "NAT")
+WABT_TOKEN_FIRST(Literal, Float)
+WABT_TOKEN_LAST(Literal, Nat)
+
+/* Tokens with Opcode data. */
+WABT_TOKEN(AtomicFence, "atomic.fence")
+WABT_TOKEN(AtomicLoad, "ATOMIC_LOAD")
+WABT_TOKEN(AtomicNotify, "ATOMIC_NOTIFY")
+WABT_TOKEN(AtomicRmw, "ATOMIC_RMW")
+WABT_TOKEN(AtomicRmwCmpxchg, "ATOMIC_RMW_CMPXCHG")
+WABT_TOKEN(AtomicStore, "ATOMIC_STORE")
+WABT_TOKEN(AtomicWait, "ATOMIC_WAIT")
+WABT_TOKEN(Binary, "BINARY")
+WABT_TOKEN(Block, "block")
+WABT_TOKEN(Br, "br")
+WABT_TOKEN(BrIf, "br_if")
+WABT_TOKEN(BrTable, "br_table")
+WABT_TOKEN(Call, "call")
+WABT_TOKEN(CallIndirect, "call_indirect")
+WABT_TOKEN(CallRef, "call_ref")
+WABT_TOKEN(Catch, "catch")
+WABT_TOKEN(CatchAll, "catch_all")
+WABT_TOKEN(Compare, "COMPARE")
+WABT_TOKEN(Const, "CONST")
+WABT_TOKEN(Convert, "CONVERT")
+WABT_TOKEN(DataDrop, "data.drop")
+WABT_TOKEN(Drop, "drop")
+WABT_TOKEN(ElemDrop, "elem.drop")
+WABT_TOKEN(Else, "else")
+WABT_TOKEN(End, "end")
+WABT_TOKEN(GlobalGet, "global.get")
+WABT_TOKEN(GlobalSet, "global.set")
+WABT_TOKEN(If, "if")
+WABT_TOKEN(Load, "LOAD")
+WABT_TOKEN(LocalGet, "local.get")
+WABT_TOKEN(LocalSet, "local.set")
+WABT_TOKEN(LocalTee, "local.tee")
+WABT_TOKEN(Loop, "loop")
+WABT_TOKEN(MemoryCopy, "memory.copy")
+WABT_TOKEN(MemoryFill, "memory.fill")
+WABT_TOKEN(MemoryGrow, "memory.grow")
+WABT_TOKEN(MemoryInit, "memory.init")
+WABT_TOKEN(MemorySize, "memory.size")
+WABT_TOKEN(Nop, "nop")
+WABT_TOKEN(RefExtern, "ref.extern")
+WABT_TOKEN(RefFunc, "ref.func")
+WABT_TOKEN(RefIsNull, "ref.is_null")
+WABT_TOKEN(RefNull, "ref.null")
+WABT_TOKEN(Rethrow, "rethrow")
+WABT_TOKEN(ReturnCallIndirect, "return_call_indirect")
+WABT_TOKEN(ReturnCall, "return_call")
+WABT_TOKEN(Return, "return")
+WABT_TOKEN(Select, "select")
+WABT_TOKEN(SimdLaneOp, "SIMDLANEOP")
+WABT_TOKEN(SimdLoadSplat, "SIMDLOADSPLAT")
+WABT_TOKEN(SimdLoadLane, "SIMDLOADLANE")
+WABT_TOKEN(SimdStoreLane, "SIMDSTORELANE")
+WABT_TOKEN(SimdShuffleOp, "i8x16.shuffle")
+WABT_TOKEN(Store, "STORE")
+WABT_TOKEN(TableCopy, "table.copy")
+WABT_TOKEN(TableFill, "table.full")
+WABT_TOKEN(TableGet, "table.get")
+WABT_TOKEN(TableGrow, "table.grow")
+WABT_TOKEN(TableInit, "table.init")
+WABT_TOKEN(TableSet, "table.set")
+WABT_TOKEN(TableSize, "table.size")
+WABT_TOKEN(Ternary, "TERNARY")
+WABT_TOKEN(Throw, "throw")
+WABT_TOKEN(Try, "try")
+WABT_TOKEN(Unary, "UNARY")
+WABT_TOKEN(Unreachable, "unreachable")
+WABT_TOKEN_FIRST(Opcode, AtomicFence)
+WABT_TOKEN_LAST(Opcode, Unreachable)
+
+/* Tokens with string data. */
+WABT_TOKEN(AlignEqNat, "align=")
+WABT_TOKEN(LparAnn, "Annotation")
+WABT_TOKEN(OffsetEqNat, "offset=")
+WABT_TOKEN(Reserved, "Reserved")
+WABT_TOKEN(Text, "TEXT")
+WABT_TOKEN(Var, "VAR")
+WABT_TOKEN_FIRST(String, AlignEqNat)
+WABT_TOKEN_LAST(String, Var)
+
+/* Tokens with Type data. */
+WABT_TOKEN(ValueType, "VALUETYPE")
+WABT_TOKEN_FIRST(Type, ValueType)
+WABT_TOKEN_LAST(Type, ValueType)
+
+/* Tokens with Type data, but are reference kinds. */
+WABT_TOKEN(Func, "func")
+WABT_TOKEN(Extern, "extern")
+WABT_TOKEN(Exn, "exn")
+WABT_TOKEN_FIRST(RefKind, Func)
+WABT_TOKEN_LAST(RefKind, Exn)
diff --git a/third_party/wasm2c/include/wabt/token.h b/third_party/wasm2c/include/wabt/token.h
new file mode 100644
index 0000000000..7d17e1066c
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/token.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_TOKEN_H_
+#define WABT_TOKEN_H_
+
+#include <string_view>
+
+#include "wabt/literal.h"
+#include "wabt/opcode.h"
+
+namespace wabt {
+
+struct Literal {
+ Literal() = default;
+ Literal(LiteralType type, std::string_view text) : type(type), text(text) {}
+
+ LiteralType type;
+ std::string_view text;
+};
+
+enum class TokenType {
+#define WABT_TOKEN(name, string) name,
+#define WABT_TOKEN_FIRST(group, first) First_##group = first,
+#define WABT_TOKEN_LAST(group, last) Last_##group = last,
+#include "wabt/token.def"
+#undef WABT_TOKEN
+#undef WABT_TOKEN_FIRST
+#undef WABT_TOKEN_LAST
+
+ First = First_Bare,
+ Last = Last_RefKind,
+};
+
+const char* GetTokenTypeName(TokenType);
+
+inline bool IsTokenTypeBare(TokenType token_type) {
+ return token_type >= TokenType::First_Bare &&
+ token_type <= TokenType::Last_Bare;
+}
+
+inline bool IsTokenTypeString(TokenType token_type) {
+ return token_type >= TokenType::First_String &&
+ token_type <= TokenType::Last_String;
+}
+
+inline bool IsTokenTypeType(TokenType token_type) {
+ return token_type == TokenType::ValueType;
+}
+
+inline bool IsTokenTypeOpcode(TokenType token_type) {
+ return token_type >= TokenType::First_Opcode &&
+ token_type <= TokenType::Last_Opcode;
+}
+
+inline bool IsTokenTypeLiteral(TokenType token_type) {
+ return token_type >= TokenType::First_Literal &&
+ token_type <= TokenType::Last_Literal;
+}
+
+inline bool IsTokenTypeRefKind(TokenType token_type) {
+ return token_type >= TokenType::First_RefKind &&
+ token_type <= TokenType::Last_RefKind;
+}
+
+struct Token {
+ Token() : token_type_(TokenType::Invalid) {}
+ Token(Location, TokenType);
+ Token(Location, TokenType, Type);
+ Token(Location, TokenType, std::string_view);
+ Token(Location, TokenType, Opcode);
+ Token(Location, TokenType, const Literal&);
+
+ Location loc;
+
+ TokenType token_type() const { return token_type_; }
+
+ bool HasText() const { return IsTokenTypeString(token_type_); }
+ bool HasType() const {
+ return IsTokenTypeType(token_type_) || IsTokenTypeRefKind(token_type_);
+ }
+ bool HasOpcode() const { return IsTokenTypeOpcode(token_type_); }
+ bool HasLiteral() const { return IsTokenTypeLiteral(token_type_); }
+
+ std::string_view text() const {
+ assert(HasText());
+ return text_;
+ }
+
+ Type type() const {
+ assert(HasType());
+ return type_;
+ }
+
+ Opcode opcode() const {
+ assert(HasOpcode());
+ return opcode_;
+ }
+
+ const Literal& literal() const {
+ assert(HasLiteral());
+ return literal_;
+ }
+
+ std::string to_string() const;
+ std::string to_string_clamp(size_t max_length) const;
+
+ private:
+ TokenType token_type_;
+
+ union {
+ std::string_view text_;
+ Type type_;
+ Opcode opcode_;
+ Literal literal_;
+ };
+};
+
+} // namespace wabt
+
+#endif // WABT_TOKEN_H_
diff --git a/third_party/wasm2c/include/wabt/tracing.h b/third_party/wasm2c/include/wabt/tracing.h
new file mode 100644
index 0000000000..5be3faa3e4
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/tracing.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_TRACING_H_
+#define WABT_TRACING_H_
+
+// Provides a simple tracing class that automatically generates enter/exit
+// messages using the scope of the instance.
+//
+// It also assumes that this file is only included in .cc files.
+// Immediately before the inclusion of this file, there is a define of
+// for WABT_TRACING, defining whether tracing should be compiled in for
+// that source file.
+
+#ifndef WABT_TRACING
+#define WABT_TRACING 0
+#endif
+
+#include "wabt/common.h"
+
+namespace wabt {
+
+#if WABT_TRACING
+
+// Scoped class that automatically prints enter("->") and exit("<-")
+// lines, indented by trace level.
+struct TraceScope {
+ WABT_DISALLOW_COPY_AND_ASSIGN(TraceScope);
+ TraceScope() = delete;
+ TraceScope(const char* method);
+ template <typename... Args>
+ TraceScope(const char* method, const char* format, Args&&... args)
+ : method_(method) {
+ PrintEnter(method);
+ fprintf(stderr, format, std::forward<Args>(args)...);
+ PrintNewline();
+ }
+ ~TraceScope();
+
+ private:
+ const char* method_;
+ void PrintEnter(const char* method);
+ void PrintNewline();
+};
+
+#define WABT_TRACE(method_name) TraceScope _func_(#method_name)
+
+#define WABT_TRACE_ARGS(method_name, format, ...) \
+ TraceScope _func_(#method_name, format, __VA_ARGS__)
+
+#else
+
+#define WABT_TRACE(method)
+#define WABT_TRACE_ARGS(method_name, format, ...)
+
+#endif
+
+} // end namespace wabt
+
+#endif // WABT_TRACING_H_
diff --git a/third_party/wasm2c/include/wabt/type-checker.h b/third_party/wasm2c/include/wabt/type-checker.h
new file mode 100644
index 0000000000..2b0ec092fe
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/type-checker.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_TYPE_CHECKER_H_
+#define WABT_TYPE_CHECKER_H_
+
+#include <functional>
+#include <vector>
+
+#include "wabt/common.h"
+#include "wabt/feature.h"
+#include "wabt/opcode.h"
+
+namespace wabt {
+
+class TypeChecker {
+ public:
+ using ErrorCallback = std::function<void(const char* msg)>;
+
+ struct Label {
+ Label(LabelType,
+ const TypeVector& param_types,
+ const TypeVector& result_types,
+ size_t limit);
+
+ TypeVector& br_types() {
+ return label_type == LabelType::Loop ? param_types : result_types;
+ }
+
+ LabelType label_type;
+ TypeVector param_types;
+ TypeVector result_types;
+ size_t type_stack_limit;
+ bool unreachable;
+ };
+
+ explicit TypeChecker(const Features& features) : features_(features) {}
+
+ void set_error_callback(const ErrorCallback& error_callback) {
+ error_callback_ = error_callback;
+ }
+
+ size_t type_stack_size() const { return type_stack_.size(); }
+
+ bool IsUnreachable();
+ Result GetLabel(Index depth, Label** out_label);
+ Result GetRethrowLabel(Index depth, Label** out_label);
+ Result GetCatchCount(Index depth, Index* out_depth);
+
+ Result BeginFunction(const TypeVector& sig);
+ Result OnAtomicFence(uint32_t consistency_model);
+ Result OnAtomicLoad(Opcode, const Limits& limits);
+ Result OnAtomicNotify(Opcode, const Limits& limits);
+ Result OnAtomicStore(Opcode, const Limits& limits);
+ Result OnAtomicRmw(Opcode, const Limits& limits);
+ Result OnAtomicRmwCmpxchg(Opcode, const Limits& limits);
+ Result OnAtomicWait(Opcode, const Limits& limits);
+ Result OnBinary(Opcode);
+ Result OnBlock(const TypeVector& param_types, const TypeVector& result_types);
+ Result OnBr(Index depth);
+ Result OnBrIf(Index depth);
+ Result BeginBrTable();
+ Result OnBrTableTarget(Index depth);
+ Result EndBrTable();
+ Result OnCall(const TypeVector& param_types, const TypeVector& result_types);
+ Result OnCallIndirect(const TypeVector& param_types,
+ const TypeVector& result_types);
+ Result OnIndexedFuncRef(Index* out_index);
+ Result OnReturnCall(const TypeVector& param_types,
+ const TypeVector& result_types);
+ Result OnReturnCallIndirect(const TypeVector& param_types,
+ const TypeVector& result_types);
+ Result OnCatch(const TypeVector& sig);
+ Result OnCompare(Opcode);
+ Result OnConst(Type);
+ Result OnConvert(Opcode);
+ Result OnDelegate(Index depth);
+ Result OnDrop();
+ Result OnElse();
+ Result OnEnd();
+ Result OnGlobalGet(Type);
+ Result OnGlobalSet(Type);
+ Result OnIf(const TypeVector& param_types, const TypeVector& result_types);
+ Result OnLoad(Opcode, const Limits& limits);
+ Result OnLocalGet(Type);
+ Result OnLocalSet(Type);
+ Result OnLocalTee(Type);
+ Result OnLoop(const TypeVector& param_types, const TypeVector& result_types);
+ Result OnMemoryCopy(const Limits& srclimits, const Limits& dstlimits);
+ Result OnDataDrop(Index);
+ Result OnMemoryFill(const Limits& limits);
+ Result OnMemoryGrow(const Limits& limits);
+ Result OnMemoryInit(Index, const Limits& limits);
+ Result OnMemorySize(const Limits& limits);
+ Result OnTableCopy();
+ Result OnElemDrop(Index);
+ Result OnTableInit(Index, Index);
+ Result OnTableGet(Type elem_type);
+ Result OnTableSet(Type elem_type);
+ Result OnTableGrow(Type elem_type);
+ Result OnTableSize();
+ Result OnTableFill(Type elem_type);
+ Result OnRefFuncExpr(Index func_type);
+ Result OnRefNullExpr(Type type);
+ Result OnRefIsNullExpr();
+ Result OnRethrow(Index depth);
+ Result OnReturn();
+ Result OnSelect(const TypeVector& result_types);
+ Result OnSimdLaneOp(Opcode, uint64_t);
+ Result OnSimdLoadLane(Opcode, const Limits& limits, uint64_t);
+ Result OnSimdStoreLane(Opcode, const Limits& limits, uint64_t);
+ Result OnSimdShuffleOp(Opcode, v128);
+ Result OnStore(Opcode, const Limits& limits);
+ Result OnTernary(Opcode);
+ Result OnThrow(const TypeVector& sig);
+ Result OnTry(const TypeVector& param_types, const TypeVector& result_types);
+ Result OnUnary(Opcode);
+ Result OnUnreachable();
+ Result EndFunction();
+
+ Result BeginInitExpr(Type type);
+ Result EndInitExpr();
+
+ static Result CheckType(Type actual, Type expected);
+
+ private:
+ void WABT_PRINTF_FORMAT(2, 3) PrintError(const char* fmt, ...);
+ Result TopLabel(Label** out_label);
+ void ResetTypeStackToLabel(Label* label);
+ Result SetUnreachable();
+ void PushLabel(LabelType label_type,
+ const TypeVector& param_types,
+ const TypeVector& result_types);
+ Result PopLabel();
+ Result CheckLabelType(Label* label, LabelType label_type);
+ Result Check2LabelTypes(Label* label,
+ LabelType label_type1,
+ LabelType label_type2);
+ Result GetThisFunctionLabel(Label** label);
+ Result PeekType(Index depth, Type* out_type);
+ Result PeekAndCheckType(Index depth, Type expected);
+ Result DropTypes(size_t drop_count);
+ void PushType(Type type);
+ void PushTypes(const TypeVector& types);
+ Result CheckTypeStackEnd(const char* desc);
+ Result CheckTypes(const TypeVector& actual, const TypeVector& expected);
+ Result CheckSignature(const TypeVector& sig, const char* desc);
+ Result CheckReturnSignature(const TypeVector& sig,
+ const TypeVector& expected,
+ const char* desc);
+ Result PopAndCheckSignature(const TypeVector& sig, const char* desc);
+ Result PopAndCheckCall(const TypeVector& param_types,
+ const TypeVector& result_types,
+ const char* desc);
+ Result PopAndCheck1Type(Type expected, const char* desc);
+ Result PopAndCheck2Types(Type expected1, Type expected2, const char* desc);
+ Result PopAndCheck3Types(Type expected1,
+ Type expected2,
+ Type expected3,
+ const char* desc);
+ Result CheckOpcode1(Opcode opcode, const Limits* limits = nullptr);
+ Result CheckOpcode2(Opcode opcode, const Limits* limits = nullptr);
+ Result CheckOpcode3(Opcode opcode,
+ const Limits* limits1 = nullptr,
+ const Limits* limits2 = nullptr,
+ const Limits* limits3 = nullptr);
+ Result OnEnd(Label* label, const char* sig_desc, const char* end_desc);
+
+ template <typename... Args>
+ void PrintStackIfFailed(Result result, const char* desc, Args... args) {
+ // Minor optimization, check result before constructing the vector to pass
+ // to the other overload of PrintStackIfFailed.
+ if (Failed(result)) {
+ PrintStackIfFailedV(result, desc, {args...}, /*is_end=*/false);
+ }
+ }
+
+ void PrintStackIfFailedV(Result,
+ const char* desc,
+ const TypeVector&,
+ bool is_end);
+
+ ErrorCallback error_callback_;
+ TypeVector type_stack_;
+ std::vector<Label> label_stack_;
+ // Cache the expected br_table signature. It will be initialized to `nullptr`
+ // to represent "any".
+ TypeVector* br_table_sig_ = nullptr;
+ Features features_;
+};
+
+} // namespace wabt
+
+#endif /* WABT_TYPE_CHECKER_H_ */
diff --git a/third_party/wasm2c/include/wabt/type.h b/third_party/wasm2c/include/wabt/type.h
new file mode 100644
index 0000000000..96fcf94588
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/type.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#ifndef WABT_TYPE_H_
+#define WABT_TYPE_H_
+
+#include <cassert>
+#include <cstdint>
+#include <vector>
+
+#include "wabt/config.h"
+#include "wabt/base-types.h"
+#include "wabt/string-format.h"
+
+namespace wabt {
+
+class Type;
+
+using TypeVector = std::vector<Type>;
+
+class Type {
+ public:
+ // Matches binary format, do not change.
+ enum Enum : int32_t {
+ I32 = -0x01, // 0x7f
+ I64 = -0x02, // 0x7e
+ F32 = -0x03, // 0x7d
+ F64 = -0x04, // 0x7c
+ V128 = -0x05, // 0x7b
+ I8 = -0x06, // 0x7a : packed-type only, used in gc and as v128 lane
+ I16 = -0x07, // 0x79 : packed-type only, used in gc and as v128 lane
+ FuncRef = -0x10, // 0x70
+ ExternRef = -0x11, // 0x6f
+ Reference = -0x15, // 0x6b
+ Func = -0x20, // 0x60
+ Struct = -0x21, // 0x5f
+ Array = -0x22, // 0x5e
+ Void = -0x40, // 0x40
+ ___ = Void, // Convenient for the opcode table in opcode.h
+
+ Any = 0, // Not actually specified, but useful for type-checking
+ I8U = 4, // Not actually specified, but used internally with load/store
+ I16U = 6, // Not actually specified, but used internally with load/store
+ I32U = 7, // Not actually specified, but used internally with load/store
+ };
+
+ Type() = default; // Provided so Type can be member of a union.
+ Type(int32_t code)
+ : enum_(static_cast<Enum>(code)), type_index_(kInvalidIndex) {}
+ Type(Enum e) : enum_(e), type_index_(kInvalidIndex) {}
+ Type(Enum e, Index type_index) : enum_(e), type_index_(type_index) {
+ assert(e == Enum::Reference);
+ }
+ constexpr operator Enum() const { return enum_; }
+
+ bool IsRef() const {
+ return enum_ == Type::ExternRef || enum_ == Type::FuncRef ||
+ enum_ == Type::Reference;
+ }
+
+ bool IsReferenceWithIndex() const { return enum_ == Type::Reference; }
+
+ bool IsNullableRef() const {
+ // Currently all reftypes are nullable
+ return IsRef();
+ }
+
+ std::string GetName() const {
+ switch (enum_) {
+ case Type::I32: return "i32";
+ case Type::I64: return "i64";
+ case Type::F32: return "f32";
+ case Type::F64: return "f64";
+ case Type::V128: return "v128";
+ case Type::I8: return "i8";
+ case Type::I16: return "i16";
+ case Type::FuncRef: return "funcref";
+ case Type::Func: return "func";
+ case Type::Void: return "void";
+ case Type::Any: return "any";
+ case Type::ExternRef: return "externref";
+ case Type::Reference:
+ return StringPrintf("(ref %d)", type_index_);
+ default:
+ return StringPrintf("<type_index[%d]>", enum_);
+ }
+ }
+
+ const char* GetRefKindName() const {
+ switch (enum_) {
+ case Type::FuncRef: return "func";
+ case Type::ExternRef: return "extern";
+ case Type::Struct: return "struct";
+ case Type::Array: return "array";
+ default: return "<invalid>";
+ }
+ }
+
+ // Functions for handling types that are an index into the type section.
+ // These are always positive integers. They occur in the binary format in
+ // block signatures, e.g.
+ //
+ // (block (result i32 i64) ...)
+ //
+ // is encoded as
+ //
+ // (type $T (func (result i32 i64)))
+ // ...
+ // (block (type $T) ...)
+ //
+ bool IsIndex() const { return static_cast<int32_t>(enum_) >= 0; }
+
+ Index GetIndex() const {
+ assert(IsIndex());
+ return static_cast<Index>(enum_);
+ }
+
+ Index GetReferenceIndex() const {
+ assert(enum_ == Enum::Reference);
+ return type_index_;
+ }
+
+ TypeVector GetInlineVector() const {
+ assert(!IsIndex());
+ switch (enum_) {
+ case Type::Void:
+ return TypeVector();
+
+ case Type::I32:
+ case Type::I64:
+ case Type::F32:
+ case Type::F64:
+ case Type::V128:
+ case Type::FuncRef:
+ case Type::ExternRef:
+ case Type::Reference:
+ return TypeVector(this, this + 1);
+
+ default:
+ WABT_UNREACHABLE;
+ }
+ }
+
+ private:
+ Enum enum_;
+ Index type_index_; // Only used for for Type::Reference
+};
+
+} // namespace wabt
+
+#endif // WABT_TYPE_H_
diff --git a/third_party/wasm2c/include/wabt/utf8.h b/third_party/wasm2c/include/wabt/utf8.h
new file mode 100644
index 0000000000..9e3b9ebdaf
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/utf8.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#ifndef WABT_UTF8_H_
+#define WABT_UTF8_H_
+
+#include <cstddef>
+
+namespace wabt {
+
+bool IsValidUtf8(const char* s, size_t length);
+
+} // namespace wabt
+
+#endif // WABT_UTF8_H_
diff --git a/third_party/wasm2c/include/wabt/validator.h b/third_party/wasm2c/include/wabt/validator.h
new file mode 100644
index 0000000000..f5b945884e
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/validator.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_VALIDATOR_H_
+#define WABT_VALIDATOR_H_
+
+#include "wabt/error.h"
+#include "wabt/feature.h"
+#include "wabt/shared-validator.h"
+
+namespace wabt {
+
+struct Module;
+struct Script;
+
+// Perform all checks on the script. It is valid if and only if this function
+// succeeds.
+Result ValidateScript(const Script*, Errors*, const ValidateOptions&);
+Result ValidateModule(const Module*, Errors*, const ValidateOptions&);
+
+} // namespace wabt
+
+#endif // WABT_VALIDATOR_H_
diff --git a/third_party/wasm2c/include/wabt/wast-lexer.h b/third_party/wasm2c/include/wabt/wast-lexer.h
new file mode 100644
index 0000000000..80bdfe7bb4
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/wast-lexer.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_WAST_LEXER_H_
+#define WABT_WAST_LEXER_H_
+
+#include <cstddef>
+#include <cstdio>
+#include <memory>
+
+#include "wabt/common.h"
+#include "wabt/error.h"
+#include "wabt/lexer-source-line-finder.h"
+#include "wabt/literal.h"
+#include "wabt/opcode.h"
+#include "wabt/token.h"
+
+namespace wabt {
+
+class ErrorHandler;
+class LexerSource;
+
+class WastLexer {
+ public:
+ WABT_DISALLOW_COPY_AND_ASSIGN(WastLexer);
+
+ WastLexer(std::unique_ptr<LexerSource> source,
+ std::string_view filename,
+ Errors*);
+
+ // Convenience functions.
+ static std::unique_ptr<WastLexer> CreateBufferLexer(std::string_view filename,
+ const void* data,
+ size_t size,
+ Errors*);
+
+ Token GetToken();
+
+ // TODO(binji): Move this out of the lexer.
+ std::unique_ptr<LexerSourceLineFinder> MakeLineFinder() {
+ return std::make_unique<LexerSourceLineFinder>(source_->Clone());
+ }
+
+ private:
+ static constexpr int kEof = -1;
+ enum class CharClass { IdChar = 1, Keyword = 2, HexDigit = 4, Digit = 8 };
+
+ Location GetLocation();
+ std::string_view GetText(size_t offset = 0);
+
+ Token BareToken(TokenType);
+ Token LiteralToken(TokenType, LiteralType);
+ Token TextToken(TokenType, size_t offset = 0);
+
+ int PeekChar();
+ int ReadChar();
+ bool MatchChar(char);
+ bool MatchString(std::string_view);
+ void Newline();
+ bool ReadBlockComment(); // Returns false if EOF.
+ bool ReadLineComment(); // Returns false if EOF.
+ void ReadWhitespace();
+
+ static bool IsCharClass(int c, CharClass);
+ static bool IsDigit(int c) { return IsCharClass(c, CharClass::Digit); }
+ static bool IsHexDigit(int c) { return IsCharClass(c, CharClass::HexDigit); }
+ static bool IsKeyword(int c) { return IsCharClass(c, CharClass::Keyword); }
+ static bool IsIdChar(int c) { return IsCharClass(c, CharClass::IdChar); }
+
+ bool ReadNum();
+ bool ReadHexNum();
+
+ enum class ReservedChars { None, Some, Id };
+ ReservedChars ReadReservedChars();
+ bool NoTrailingReservedChars() {
+ return ReadReservedChars() == ReservedChars::None;
+ }
+ void ReadSign();
+ Token GetStringToken();
+ Token GetNumberToken(TokenType);
+ Token GetHexNumberToken(TokenType);
+ Token GetInfToken();
+ Token GetNanToken();
+ Token GetNameEqNumToken(std::string_view name, TokenType);
+ Token GetIdChars();
+ Token GetKeywordToken();
+ Token GetReservedToken();
+
+ std::unique_ptr<LexerSource> source_;
+ std::string filename_;
+ int line_;
+ const char* buffer_;
+ const char* buffer_end_;
+ const char* line_start_;
+ const char* token_start_;
+ const char* cursor_;
+
+ Errors* errors_;
+ void WABT_PRINTF_FORMAT(3, 4) Error(Location, const char* format, ...);
+};
+
+} // namespace wabt
+
+#endif /* WABT_WAST_LEXER_H_ */
diff --git a/third_party/wasm2c/include/wabt/wast-parser.h b/third_party/wasm2c/include/wabt/wast-parser.h
new file mode 100644
index 0000000000..09b4e5377e
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/wast-parser.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_WAST_PARSER_H_
+#define WABT_WAST_PARSER_H_
+
+#include <array>
+#include <memory>
+#include <unordered_map>
+
+#include "wabt/circular-array.h"
+#include "wabt/error.h"
+#include "wabt/feature.h"
+#include "wabt/intrusive-list.h"
+#include "wabt/ir.h"
+#include "wabt/wast-lexer.h"
+
+namespace wabt {
+
+struct WastParseOptions {
+ WastParseOptions(const Features& features) : features(features) {}
+
+ Features features;
+ bool debug_parsing = false;
+};
+
+using TokenTypePair = std::array<TokenType, 2>;
+
+class WastParser {
+ public:
+ WastParser(WastLexer*, Errors*, WastParseOptions*);
+
+ void WABT_PRINTF_FORMAT(3, 4) Error(Location, const char* format, ...);
+ Result ParseModule(std::unique_ptr<Module>* out_module);
+ Result ParseScript(std::unique_ptr<Script>* out_script);
+
+ std::unique_ptr<Script> ReleaseScript();
+
+ private:
+ enum class ConstType {
+ Normal,
+ Expectation,
+ };
+
+ void ErrorUnlessOpcodeEnabled(const Token&);
+
+ // Print an error message listing the expected tokens, as well as an example
+ // of expected input.
+ Result ErrorExpected(const std::vector<std::string>& expected,
+ const char* example = nullptr);
+
+ // Print an error message, and and return Result::Error if the next token is
+ // '('. This is commonly used after parsing a sequence of s-expressions -- if
+ // no more can be parsed, we know that a following '(' is invalid. This
+ // function consumes the '(' so a better error message can be provided
+ // (assuming the following token was unexpected).
+ Result ErrorIfLpar(const std::vector<std::string>& expected,
+ const char* example = nullptr);
+
+ // Returns the next token without consuming it.
+ Token GetToken();
+
+ // Returns the location of the next token.
+ Location GetLocation();
+
+ // Returns the type of the next token.
+ TokenType Peek(size_t n = 0);
+
+ // Returns the types of the next two tokens.
+ TokenTypePair PeekPair();
+
+ // Returns true if the next token's type is equal to the parameter.
+ bool PeekMatch(TokenType, size_t n = 0);
+
+ // Returns true if the next token's type is '(' and the following token is
+ // equal to the parameter.
+ bool PeekMatchLpar(TokenType);
+
+ // Returns true if the next two tokens can start an Expr. This allows for
+ // folded expressions, plain instructions and block instructions.
+ bool PeekMatchExpr();
+
+ // Returns true if the next two tokens are form reference type - (ref $t)
+ bool PeekMatchRefType();
+
+ // Returns true if the next token's type is equal to the parameter. If so,
+ // then the token is consumed.
+ bool Match(TokenType);
+
+ // Returns true if the next token's type is equal to '(' and the following
+ // token is equal to the parameter. If so, then the token is consumed.
+ bool MatchLpar(TokenType);
+
+ // Like Match(), but prints an error message if the token doesn't match, and
+ // returns Result::Error.
+ Result Expect(TokenType);
+
+ // Consume one token and return it.
+ Token Consume();
+
+ // Give the Match() function a clearer name when used to optionally consume a
+ // token (used for printing better error messages).
+ void ConsumeIfLpar() { Match(TokenType::Lpar); }
+
+ using SynchronizeFunc = bool(*)(TokenTypePair pair);
+
+ // Attempt to synchronize the token stream by dropping tokens until the
+ // SynchronizeFunc returns true, or until a token limit is reached. This
+ // function returns Result::Error if the stream was not able to be
+ // synchronized.
+ Result Synchronize(SynchronizeFunc);
+
+ bool ParseBindVarOpt(std::string* name);
+ Result ParseVar(Var* out_var);
+ bool ParseVarOpt(Var* out_var, Var default_var = Var());
+ Result ParseOffsetExpr(ExprList* out_expr_list);
+ bool ParseOffsetExprOpt(ExprList* out_expr_list);
+ Result ParseTextList(std::vector<uint8_t>* out_data);
+ bool ParseTextListOpt(std::vector<uint8_t>* out_data);
+ Result ParseVarList(VarVector* out_var_list);
+ bool ParseElemExprOpt(ExprList* out_elem_expr);
+ bool ParseElemExprListOpt(ExprListVector* out_list);
+ bool ParseElemExprVarListOpt(ExprListVector* out_list);
+ Result ParseValueType(Var* out_type);
+ Result ParseValueTypeList(
+ TypeVector* out_type_list,
+ std::unordered_map<uint32_t, std::string>* type_names);
+ Result ParseRefKind(Type* out_type);
+ Result ParseRefType(Type* out_type);
+ bool ParseRefTypeOpt(Type* out_type);
+ Result ParseQuotedText(std::string* text, bool check_utf8 = true);
+ bool ParseOffsetOpt(Address* offset);
+ bool ParseAlignOpt(Address* align);
+ Result ParseMemidx(Location loc, Var* memidx);
+ Result ParseLimitsIndex(Limits*);
+ Result ParseLimits(Limits*);
+ Result ParseNat(uint64_t*, bool is_64);
+
+ Result ParseModuleFieldList(Module*);
+ Result ParseModuleField(Module*);
+ Result ParseDataModuleField(Module*);
+ Result ParseElemModuleField(Module*);
+ Result ParseTagModuleField(Module*);
+ Result ParseExportModuleField(Module*);
+ Result ParseFuncModuleField(Module*);
+ Result ParseTypeModuleField(Module*);
+ Result ParseGlobalModuleField(Module*);
+ Result ParseImportModuleField(Module*);
+ Result ParseMemoryModuleField(Module*);
+ Result ParseStartModuleField(Module*);
+ Result ParseTableModuleField(Module*);
+
+ Result ParseExportDesc(Export*);
+ Result ParseInlineExports(ModuleFieldList*, ExternalKind);
+ Result ParseInlineImport(Import*);
+ Result ParseTypeUseOpt(FuncDeclaration*);
+ Result ParseFuncSignature(FuncSignature*, BindingHash* param_bindings);
+ Result ParseUnboundFuncSignature(FuncSignature*);
+ Result ParseBoundValueTypeList(TokenType,
+ TypeVector*,
+ BindingHash*,
+ std::unordered_map<uint32_t, std::string>*,
+ Index binding_index_offset = 0);
+ Result ParseUnboundValueTypeList(TokenType,
+ TypeVector*,
+ std::unordered_map<uint32_t, std::string>*);
+ Result ParseResultList(TypeVector*,
+ std::unordered_map<uint32_t, std::string>*);
+ Result ParseInstrList(ExprList*);
+ Result ParseTerminatingInstrList(ExprList*);
+ Result ParseInstr(ExprList*);
+ Result ParseCodeMetadataAnnotation(ExprList*);
+ Result ParsePlainInstr(std::unique_ptr<Expr>*);
+ Result ParseF32(Const*, ConstType type);
+ Result ParseF64(Const*, ConstType type);
+ Result ParseConst(Const*, ConstType type);
+ Result ParseExpectedValues(ExpectationPtr*);
+ Result ParseEither(ConstVector*);
+ Result ParseExternref(Const*);
+ Result ParseExpectedNan(ExpectedNan* expected);
+ Result ParseConstList(ConstVector*, ConstType type);
+ Result ParseBlockInstr(std::unique_ptr<Expr>*);
+ Result ParseLabelOpt(std::string*);
+ Result ParseEndLabelOpt(const std::string&);
+ Result ParseBlockDeclaration(BlockDeclaration*);
+ Result ParseBlock(Block*);
+ Result ParseExprList(ExprList*);
+ Result ParseExpr(ExprList*);
+ Result ParseCatchInstrList(CatchVector* catches);
+ Result ParseCatchExprList(CatchVector* catches);
+ Result ParseGlobalType(Global*);
+ Result ParseField(Field*);
+ Result ParseFieldList(std::vector<Field>*);
+
+ template <typename T>
+ Result ParsePlainInstrVar(Location, std::unique_ptr<Expr>*);
+ template <typename T>
+ Result ParseMemoryInstrVar(Location, std::unique_ptr<Expr>*);
+ template <typename T>
+ Result ParseLoadStoreInstr(Location, Token, std::unique_ptr<Expr>*);
+ template <typename T>
+ Result ParseSIMDLoadStoreInstr(Location loc,
+ Token token,
+ std::unique_ptr<Expr>* out_expr);
+ template <typename T>
+ Result ParseMemoryExpr(Location, std::unique_ptr<Expr>*);
+ template <typename T>
+ Result ParseMemoryBinaryExpr(Location, std::unique_ptr<Expr>*);
+ Result ParseSimdLane(Location, uint64_t*);
+
+ Result ParseCommandList(Script*, CommandPtrVector*);
+ Result ParseCommand(Script*, CommandPtr*);
+ Result ParseAssertExceptionCommand(CommandPtr*);
+ Result ParseAssertExhaustionCommand(CommandPtr*);
+ Result ParseAssertInvalidCommand(CommandPtr*);
+ Result ParseAssertMalformedCommand(CommandPtr*);
+ Result ParseAssertReturnCommand(CommandPtr*);
+ Result ParseAssertReturnFuncCommand(CommandPtr*);
+ Result ParseAssertTrapCommand(CommandPtr*);
+ Result ParseAssertUnlinkableCommand(CommandPtr*);
+ Result ParseActionCommand(CommandPtr*);
+ Result ParseModuleCommand(Script*, CommandPtr*);
+ Result ParseRegisterCommand(CommandPtr*);
+ Result ParseInputCommand(CommandPtr*);
+ Result ParseOutputCommand(CommandPtr*);
+
+ Result ParseAction(ActionPtr*);
+ Result ParseScriptModule(std::unique_ptr<ScriptModule>*);
+
+ template <typename T>
+ Result ParseActionCommand(TokenType, CommandPtr*);
+ template <typename T>
+ Result ParseAssertActionCommand(TokenType, CommandPtr*);
+ template <typename T>
+ Result ParseAssertActionTextCommand(TokenType, CommandPtr*);
+ template <typename T>
+ Result ParseAssertScriptModuleCommand(TokenType, CommandPtr*);
+
+ Result ParseSimdV128Const(Const*, TokenType, ConstType);
+
+ void CheckImportOrdering(Module*);
+
+ WastLexer* lexer_;
+ Index last_module_index_ = kInvalidIndex;
+ Errors* errors_;
+ WastParseOptions* options_;
+
+ CircularArray<Token, 2> tokens_;
+};
+
+Result ParseWatModule(WastLexer* lexer,
+ std::unique_ptr<Module>* out_module,
+ Errors*,
+ WastParseOptions* options);
+
+Result ParseWastScript(WastLexer* lexer,
+ std::unique_ptr<Script>* out_script,
+ Errors*,
+ WastParseOptions* options);
+
+} // namespace wabt
+
+#endif /* WABT_WAST_PARSER_H_ */
diff --git a/third_party/wasm2c/include/wabt/wat-writer.h b/third_party/wasm2c/include/wabt/wat-writer.h
new file mode 100644
index 0000000000..0f19ba2465
--- /dev/null
+++ b/third_party/wasm2c/include/wabt/wat-writer.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 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.
+ */
+
+#ifndef WABT_WAT_WRITER_H_
+#define WABT_WAT_WRITER_H_
+
+#include "wabt/common.h"
+#include "wabt/feature.h"
+
+namespace wabt {
+
+struct Module;
+class Stream;
+
+struct WriteWatOptions {
+ WriteWatOptions() = default;
+ WriteWatOptions(const Features& features) : features(features) {}
+ Features features;
+ bool fold_exprs = false; // Write folded expressions.
+ bool inline_export = false;
+ bool inline_import = false;
+};
+
+Result WriteWat(Stream*, const Module*, const WriteWatOptions&);
+
+} // namespace wabt
+
+#endif /* WABT_WAT_WRITER_H_ */