diff options
Diffstat (limited to 'third_party/wasm2c/include/wabt')
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_ */ |