summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWouter van Oortmerssen <aardappel@gmail.com>2020-08-07 12:55:47 -0700
committerGitHub <noreply@github.com>2020-08-07 12:55:47 -0700
commit4b9852ad23541c851031398b835d6387b1b51393 (patch)
treec41ad109e1e54825b4da0c823c62a28a97e0ed99
parent05c1aa18e53258fefee9a8aac656280475ccf614 (diff)
downloadwabt-4b9852ad23541c851031398b835d6387b1b51393.tar.gz
wabt-4b9852ad23541c851031398b835d6387b1b51393.tar.bz2
wabt-4b9852ad23541c851031398b835d6387b1b51393.zip
Added initial "memory64" proposal support (#1500)
-rw-r--r--README.md2
-rw-r--r--src/binary-reader-ir.cc36
-rw-r--r--src/binary-reader-logging.cc4
-rw-r--r--src/binary-reader-logging.h20
-rw-r--r--src/binary-reader-nop.h20
-rw-r--r--src/binary-reader-objdump.cc25
-rw-r--r--src/binary-reader.cc98
-rw-r--r--src/binary-reader.h20
-rw-r--r--src/binary-writer.cc18
-rw-r--r--src/binary.h6
-rw-r--r--src/common.cc17
-rw-r--r--src/common.h49
-rw-r--r--src/decompiler.cc2
-rw-r--r--src/feature.def1
-rw-r--r--src/interp/binary-reader-interp.cc38
-rw-r--r--src/interp/interp-inl.h32
-rw-r--r--src/interp/interp.cc53
-rw-r--r--src/interp/interp.h42
-rw-r--r--src/ir.h4
-rw-r--r--src/leb128.cc44
-rw-r--r--src/leb128.h1
-rw-r--r--src/opcode.h8
-rw-r--r--src/shared-validator.cc70
-rw-r--r--src/type-checker.cc89
-rw-r--r--src/type-checker.h39
-rw-r--r--src/wast-parser.cc19
-rw-r--r--src/wast-parser.h4
-rw-r--r--src/wat-writer.cc3
-rw-r--r--test/binary/bad-memory-limits-flag.txt6
-rw-r--r--test/binary/bad-table-limits-flag.txt6
-rw-r--r--test/dump/bulk-memory64.txt54
-rw-r--r--test/dump/load64.txt217
-rw-r--r--test/dump/store64.txt166
-rwxr-xr-xtest/gen-spec-wast.py2
-rw-r--r--test/help/spectest-interp.txt1
-rw-r--r--test/help/wasm-interp.txt1
-rw-r--r--test/help/wasm-opcodecnt.txt1
-rw-r--r--test/help/wasm-validate.txt1
-rw-r--r--test/help/wasm2wat.txt1
-rw-r--r--test/help/wast2json.txt1
-rw-r--r--test/help/wat-desugar.txt1
-rw-r--r--test/help/wat2wasm.txt1
-rw-r--r--test/interp/load64.txt73
-rw-r--r--test/interp/store64.txt102
-rw-r--r--test/parse/expr/atomic64.txt82
-rw-r--r--test/parse/expr/bulk-memory-named64.txt19
-rw-r--r--test/parse/expr/grow-memory64.txt8
-rw-r--r--test/parse/expr/load64.txt46
-rw-r--r--test/parse/expr/memory-copy64.txt10
-rw-r--r--test/parse/expr/memory-fill64.txt10
-rw-r--r--test/parse/expr/memory-init64.txt12
-rw-r--r--test/parse/expr/store64.txt31
-rw-r--r--test/roundtrip/bulk-memory64.txt78
-rw-r--r--test/roundtrip/fold-load-store64.txt59
-rw-r--r--test/roundtrip/memory-index64.txt8
-rwxr-xr-xtest/run-roundtrip.py3
-rw-r--r--test/spec/memory.txt12
57 files changed, 1489 insertions, 287 deletions
diff --git a/README.md b/README.md
index 3363b052..9f05dcbe 100644
--- a/README.md
+++ b/README.md
@@ -56,6 +56,7 @@ Wabt has been compiled to JavaScript via emscripten. Some of the functionality i
| [bulk memory][] | `--enable-bulk-memory` | ✓ | ✓ | ✓ | ✓ |
| [reference types][] | `--enable-reference-types` | ✓ | ✓ | ✓ | ✓ |
| [annotations][] | `--enable-annotations` | | ✓ | | |
+| [memory64][] | `--enable-memory64` | | | | |
[exception handling]: https://github.com/WebAssembly/exception-handling
[mutable globals]: https://github.com/WebAssembly/mutable-global
@@ -68,6 +69,7 @@ Wabt has been compiled to JavaScript via emscripten. Some of the functionality i
[bulk memory]: https://github.com/WebAssembly/bulk-memory-operations
[reference types]: https://github.com/WebAssembly/reference-types
[annotations]: https://github.com/WebAssembly/annotations
+[memory64]: https://github.com/WebAssembly/memory64
## Cloning
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index 3b0fc453..3678438e 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -118,23 +118,23 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnLocalDecl(Index decl_index, Index count, Type type) override;
Result OnAtomicLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicRmwExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicWaitExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicFenceExpr(uint32_t consistency_model) override;
Result OnAtomicNotifyExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnBinaryExpr(Opcode opcode) override;
Result OnBlockExpr(Type sig_type) override;
@@ -163,7 +163,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnI64ConstExpr(uint64_t value) override;
Result OnIfExpr(Type sig_type) override;
Result OnLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnLocalGetExpr(Index local_index) override;
Result OnLocalSetExpr(Index local_index) override;
@@ -191,7 +191,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnReturnExpr() override;
Result OnSelectExpr(Type result_type) override;
Result OnStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnThrowExpr(Index event_index) override;
Result OnTryExpr(Type sig_type) override;
@@ -202,7 +202,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override;
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
Result OnLoadSplatExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnElemSegmentCount(Index count) override;
@@ -633,35 +633,35 @@ Result BinaryReaderIR::OnLocalDecl(Index decl_index, Index count, Type type) {
}
Result BinaryReaderIR::OnAtomicLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(
MakeUnique<AtomicLoadExpr>(opcode, 1 << alignment_log2, offset));
}
Result BinaryReaderIR::OnAtomicStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(
MakeUnique<AtomicStoreExpr>(opcode, 1 << alignment_log2, offset));
}
Result BinaryReaderIR::OnAtomicRmwExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(
MakeUnique<AtomicRmwExpr>(opcode, 1 << alignment_log2, offset));
}
Result BinaryReaderIR::OnAtomicRmwCmpxchgExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(
MakeUnique<AtomicRmwCmpxchgExpr>(opcode, 1 << alignment_log2, offset));
}
Result BinaryReaderIR::OnAtomicWaitExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(
MakeUnique<AtomicWaitExpr>(opcode, 1 << alignment_log2, offset));
@@ -672,7 +672,7 @@ Result BinaryReaderIR::OnAtomicFenceExpr(uint32_t consistency_model) {
}
Result BinaryReaderIR::OnAtomicNotifyExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(
MakeUnique<AtomicNotifyExpr>(opcode, 1 << alignment_log2, offset));
@@ -841,7 +841,7 @@ Result BinaryReaderIR::OnIfExpr(Type sig_type) {
}
Result BinaryReaderIR::OnLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(MakeUnique<LoadExpr>(opcode, 1 << alignment_log2, offset));
}
@@ -949,7 +949,7 @@ Result BinaryReaderIR::OnLocalSetExpr(Index local_index) {
}
Result BinaryReaderIR::OnStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(MakeUnique<StoreExpr>(opcode, 1 << alignment_log2, offset));
}
@@ -1016,7 +1016,7 @@ Result BinaryReaderIR::OnSimdShuffleOpExpr(Opcode opcode, v128 value) {
}
Result BinaryReaderIR::OnLoadSplatExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) {
return AppendExpr(
MakeUnique<LoadSplatExpr>(opcode, 1 << alignment_log2, offset));
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc
index e5d72772..fbc4af9c 100644
--- a/src/binary-reader-logging.cc
+++ b/src/binary-reader-logging.cc
@@ -604,7 +604,7 @@ Result BinaryReaderLogging::OnEventSymbol(Index index,
Result BinaryReaderLogging::OnSegmentInfo(Index index,
string_view name,
- uint32_t alignment,
+ Address alignment,
uint32_t flags) {
LOGF("OnSegmentInfo(%d name: " PRIstringview
", alignment: %d, flags: 0x%x)\n",
@@ -693,7 +693,7 @@ Result BinaryReaderLogging::OnComdatEntry(ComdatType kind, Index index) {
}
#define DEFINE_LOAD_STORE_OPCODE(name) \
- Result BinaryReaderLogging::name(Opcode opcode, uint32_t alignment_log2, \
+ Result BinaryReaderLogging::name(Opcode opcode, Address alignment_log2, \
Address offset) { \
LOGF(#name "(opcode: \"%s\" (%u), align log2: %u, offset: %" PRIaddress \
")\n", \
diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h
index fd1ac13f..af7a92ba 100644
--- a/src/binary-reader-logging.h
+++ b/src/binary-reader-logging.h
@@ -142,16 +142,16 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnOpcodeBlockSig(Type sig_type) override;
Result OnOpcodeType(Type type) override;
Result OnAtomicLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicRmwExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnBinaryExpr(Opcode opcode) override;
Result OnBlockExpr(Type sig_type) override;
@@ -179,7 +179,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnI64ConstExpr(uint64_t value) override;
Result OnIfExpr(Type sig_type) override;
Result OnLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnLocalGetExpr(Index local_index) override;
Result OnLocalSetExpr(Index local_index) override;
@@ -209,7 +209,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnReturnExpr() override;
Result OnSelectExpr(Type result_type) override;
Result OnStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnThrowExpr(Index event_index) override;
Result OnTryExpr(Type sig_type) override;
@@ -217,18 +217,18 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnTernaryExpr(Opcode opcode) override;
Result OnUnreachableExpr() override;
Result OnAtomicWaitExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicFenceExpr(uint32_t consistency_model) override;
Result OnAtomicNotifyExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result EndFunctionBody(Index index) override;
Result EndCodeSection() override;
Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override;
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
Result OnLoadSplatExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result BeginElemSection(Offset size) override;
@@ -328,7 +328,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnSegmentInfoCount(Index count) override;
Result OnSegmentInfo(Index index,
string_view name,
- uint32_t alignment,
+ Address alignment,
uint32_t flags) override;
Result OnInitFunctionCount(Index count) override;
Result OnInitFunction(uint32_t priority, Index function_index) override;
diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h
index a00d6b05..e186ed1e 100644
--- a/src/binary-reader-nop.h
+++ b/src/binary-reader-nop.h
@@ -192,32 +192,32 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnOpcodeBlockSig(Type sig_type) override { return Result::Ok; }
Result OnOpcodeType(Type type) override { return Result::Ok; }
Result OnAtomicLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override {
return Result::Ok;
}
Result OnAtomicStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override {
return Result::Ok;
}
Result OnAtomicRmwExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override {
return Result::Ok;
}
Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override {
return Result::Ok;
}
- Result OnAtomicWaitExpr(Opcode, uint32_t, Address) override {
+ Result OnAtomicWaitExpr(Opcode, Address, Address) override {
return Result::Ok;
}
Result OnAtomicFenceExpr(uint32_t) override {
return Result::Ok;
}
- Result OnAtomicNotifyExpr(Opcode, uint32_t, Address) override {
+ Result OnAtomicNotifyExpr(Opcode, Address, Address) override {
return Result::Ok;
}
Result OnBinaryExpr(Opcode opcode) override { return Result::Ok; }
@@ -250,7 +250,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnI64ConstExpr(uint64_t value) override { return Result::Ok; }
Result OnIfExpr(Type sig_type) override { return Result::Ok; }
Result OnLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override {
return Result::Ok;
}
@@ -286,7 +286,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnReturnExpr() override { return Result::Ok; }
Result OnSelectExpr(Type result_type) override { return Result::Ok; }
Result OnStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override {
return Result::Ok;
}
@@ -304,7 +304,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
return Result::Ok;
}
Result OnLoadSplatExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override {
return Result::Ok;
}
@@ -473,7 +473,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnSegmentInfoCount(Index count) override { return Result::Ok; }
Result OnSegmentInfo(Index index,
string_view name,
- uint32_t alignment,
+ Address alignment,
uint32_t flags) override {
return Result::Ok;
}
diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc
index 7570b8df..931db76a 100644
--- a/src/binary-reader-objdump.cc
+++ b/src/binary-reader-objdump.cc
@@ -153,7 +153,8 @@ string_view BinaryReaderObjdumpBase::GetSegmentName(Index index) const {
}
string_view BinaryReaderObjdumpBase::GetSymbolName(Index symbol_index) const {
- assert(symbol_index < objdump_state_->symtab.size());
+ if (symbol_index >= objdump_state_->symtab.size())
+ return "<illegal_symbol_index>";
ObjdumpSymbol& sym = objdump_state_->symtab[symbol_index];
switch (sym.kind) {
case SymbolType::Function:
@@ -338,7 +339,7 @@ class BinaryReaderObjdumpPrepass : public BinaryReaderObjdumpBase {
Result OnSegmentInfo(Index index,
string_view name,
- uint32_t alignment_log2,
+ Address alignment_log2,
uint32_t flags) override {
SetSegmentName(index, name);
return Result::Ok;
@@ -889,7 +890,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
Result OnSegmentInfoCount(Index count) override;
Result OnSegmentInfo(Index index,
string_view name,
- uint32_t alignment_log2,
+ Address alignment_log2,
uint32_t flags) override;
Result OnInitFunctionCount(Index count) override;
Result OnInitFunction(uint32_t priority, Index function_index) override;
@@ -1208,6 +1209,12 @@ Result BinaryReaderObjdump::OnImportMemory(Index import_index,
if (page_limits->has_max) {
PrintDetails(" max=%" PRId64, page_limits->max);
}
+ if (page_limits->is_shared) {
+ PrintDetails(" shared");
+ }
+ if (page_limits->is_64) {
+ PrintDetails(" i64");
+ }
PrintDetails(" <- " PRIstringview "." PRIstringview "\n",
WABT_PRINTF_STRING_VIEW_ARG(module_name),
WABT_PRINTF_STRING_VIEW_ARG(field_name));
@@ -1255,6 +1262,12 @@ Result BinaryReaderObjdump::OnMemory(Index index, const Limits* page_limits) {
if (page_limits->has_max) {
PrintDetails(" max=%" PRId64, page_limits->max);
}
+ if (page_limits->is_shared) {
+ PrintDetails(" shared");
+ }
+ if (page_limits->is_64) {
+ PrintDetails(" i64");
+ }
PrintDetails("\n");
return Result::Ok;
}
@@ -1775,10 +1788,10 @@ Result BinaryReaderObjdump::OnSegmentInfoCount(Index count) {
Result BinaryReaderObjdump::OnSegmentInfo(Index index,
string_view name,
- uint32_t alignment_log2,
+ Address alignment_log2,
uint32_t flags) {
- PrintDetails(" - %d: " PRIstringview " p2align=%d flags=%#x\n", index,
- WABT_PRINTF_STRING_VIEW_ARG(name), alignment_log2, flags);
+ PrintDetails(" - %d: " PRIstringview " p2align=%" PRIaddress " flags=%#x\n",
+ index, WABT_PRINTF_STRING_VIEW_ARG(name), alignment_log2, flags);
return Result::Ok;
}
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index 2ff170e3..27d6b85c 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -96,6 +96,7 @@ class BinaryReader {
Result ReadF64(uint64_t* out_value, const char* desc) WABT_WARN_UNUSED;
Result ReadV128(v128* out_value, const char* desc) WABT_WARN_UNUSED;
Result ReadU32Leb128(uint32_t* out_value, const char* desc) WABT_WARN_UNUSED;
+ Result ReadU64Leb128(uint64_t* out_value, const char* desc) WABT_WARN_UNUSED;
Result ReadS32Leb128(uint32_t* out_value, const char* desc) WABT_WARN_UNUSED;
Result ReadS64Leb128(uint64_t* out_value, const char* desc) WABT_WARN_UNUSED;
Result ReadType(Type* out_value, const char* desc) WABT_WARN_UNUSED;
@@ -108,7 +109,7 @@ class BinaryReader {
const char* desc) WABT_WARN_UNUSED;
Result ReadIndex(Index* index, const char* desc) WABT_WARN_UNUSED;
Result ReadOffset(Offset* offset, const char* desc) WABT_WARN_UNUSED;
- Result ReadAlignment(uint32_t* align_log2, const char* desc) WABT_WARN_UNUSED;
+ Result ReadAlignment(Address* align_log2, const char* desc) WABT_WARN_UNUSED;
Result ReadCount(Index* index, const char* desc) WABT_WARN_UNUSED;
Result ReadField(TypeMut* out_value) WABT_WARN_UNUSED;
@@ -124,6 +125,9 @@ class BinaryReader {
Result ReadMemory(Limits* out_page_limits) WABT_WARN_UNUSED;
Result ReadGlobalHeader(Type* out_type, bool* out_mutable) WABT_WARN_UNUSED;
Result ReadEventType(Index* out_sig_index) WABT_WARN_UNUSED;
+ Result ReadAddress(Address* out_value,
+ Index memory,
+ const char* desc) WABT_WARN_UNUSED;
Result ReadFunctionBody(Offset end_offset) WABT_WARN_UNUSED;
Result ReadNameSection(Offset section_size) WABT_WARN_UNUSED;
Result ReadRelocSection(Offset section_size) WABT_WARN_UNUSED;
@@ -166,6 +170,7 @@ class BinaryReader {
Index num_function_signatures_ = 0;
Index num_function_bodies_ = 0;
Index data_count_ = kInvalidIndex;
+ std::vector<Limits> memories;
using ReadEndRestoreGuard =
ValueRestoreGuard<size_t, &BinaryReader::read_end_>;
@@ -278,6 +283,15 @@ Result BinaryReader::ReadU32Leb128(uint32_t* out_value, const char* desc) {
return Result::Ok;
}
+Result BinaryReader::ReadU64Leb128(uint64_t* out_value, const char* desc) {
+ const uint8_t* p = state_.data + state_.offset;
+ const uint8_t* end = state_.data + read_end_;
+ size_t bytes_read = wabt::ReadU64Leb128(p, end, out_value);
+ ERROR_UNLESS(bytes_read > 0, "unable to read u64 leb128: %s", desc);
+ state_.offset += bytes_read;
+ return Result::Ok;
+}
+
Result BinaryReader::ReadS32Leb128(uint32_t* out_value, const char* desc) {
const uint8_t* p = state_.data + state_.offset;
const uint8_t* end = state_.data + read_end_;
@@ -366,7 +380,7 @@ Result BinaryReader::ReadOffset(Offset* offset, const char* desc) {
return Result::Ok;
}
-Result BinaryReader::ReadAlignment(uint32_t* alignment_log2, const char* desc) {
+Result BinaryReader::ReadAlignment(Address* alignment_log2, const char* desc) {
uint32_t value;
CHECK_RESULT(ReadU32Leb128(&value, desc));
if (value >= 32) {
@@ -544,8 +558,10 @@ Result BinaryReader::ReadTable(Type* out_elem_type, Limits* out_elem_limits) {
CHECK_RESULT(ReadU8(&flags, "table flags"));
bool has_max = flags & WABT_BINARY_LIMITS_HAS_MAX_FLAG;
bool is_shared = flags & WABT_BINARY_LIMITS_IS_SHARED_FLAG;
+ bool is_64 = flags & WABT_BINARY_LIMITS_IS_64_FLAG;
const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_FLAGS;
ERROR_IF(is_shared, "tables may not be shared");
+ ERROR_IF(is_64, "tables may not be 64-bit");
ERROR_UNLESS(unknown_flags == 0, "malformed table limits flag: %d", flags);
CHECK_RESULT(ReadU32Leb128(&initial, "table initial elem count"));
if (has_max) {
@@ -565,6 +581,7 @@ Result BinaryReader::ReadMemory(Limits* out_page_limits) {
CHECK_RESULT(ReadU8(&flags, "memory flags"));
bool has_max = flags & WABT_BINARY_LIMITS_HAS_MAX_FLAG;
bool is_shared = flags & WABT_BINARY_LIMITS_IS_SHARED_FLAG;
+ bool is_64 = flags & WABT_BINARY_LIMITS_IS_64_FLAG;
const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_FLAGS;
ERROR_UNLESS(unknown_flags == 0, "malformed memory limits flag: %d", flags);
ERROR_IF(is_shared && !options_.features.threads_enabled(),
@@ -576,8 +593,12 @@ Result BinaryReader::ReadMemory(Limits* out_page_limits) {
out_page_limits->has_max = has_max;
out_page_limits->is_shared = is_shared;
+ out_page_limits->is_64 = is_64;
out_page_limits->initial = initial;
out_page_limits->max = max;
+
+ // Have to keep a copy of these, to know how to interpret load/stores.
+ memories.push_back(*out_page_limits);
return Result::Ok;
}
@@ -596,6 +617,22 @@ Result BinaryReader::ReadGlobalHeader(Type* out_type, bool* out_mutable) {
return Result::Ok;
}
+Result BinaryReader::ReadAddress(Address* out_value,
+ Index memory,
+ const char* desc) {
+ ERROR_UNLESS(memory < memories.size(),
+ "load/store memory %u out of range %lu", memory,
+ memories.size());
+ if (memories[memory].is_64) {
+ return ReadU64Leb128(out_value, desc);
+ } else {
+ uint32_t val;
+ Result res = ReadU32Leb128(&val, desc);
+ *out_value = val;
+ return res;
+ }
+}
+
Result BinaryReader::ReadFunctionBody(Offset end_offset) {
bool seen_end_opcode = false;
while (state_.offset < end_offset) {
@@ -878,10 +915,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::I32X4Load16X4U:
case Opcode::I64X2Load32X2S:
case Opcode::I64X2Load32X2U: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "load alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "load offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "load offset"));
CALLBACK(OnLoadExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
break;
@@ -897,10 +934,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::F32Store:
case Opcode::F64Store:
case Opcode::V128Store: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "store alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "store offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "store offset"));
CALLBACK(OnStoreExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
@@ -1213,10 +1250,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::V16X8LoadSplat:
case Opcode::V32X4LoadSplat:
case Opcode::V64X2LoadSplat: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "load alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "load offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "load offset"));
CALLBACK(OnLoadSplatExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
@@ -1319,10 +1356,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
break;
case Opcode::AtomicNotify: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "load alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "load offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "load offset"));
CALLBACK(OnAtomicNotifyExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
@@ -1331,10 +1368,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::I32AtomicWait:
case Opcode::I64AtomicWait: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "load alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "load offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "load offset"));
CALLBACK(OnAtomicWaitExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
@@ -1358,10 +1395,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::I64AtomicLoad32U:
case Opcode::I32AtomicLoad:
case Opcode::I64AtomicLoad: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "load alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "load offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "load offset"));
CALLBACK(OnAtomicLoadExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
@@ -1375,10 +1412,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::I64AtomicStore32:
case Opcode::I32AtomicStore:
case Opcode::I64AtomicStore: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "store alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "store offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "store offset"));
CALLBACK(OnAtomicStoreExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
@@ -1427,10 +1464,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::I64AtomicRmw8XchgU:
case Opcode::I64AtomicRmw16XchgU:
case Opcode::I64AtomicRmw32XchgU: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "memory alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "memory offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "memory offset"));
CALLBACK(OnAtomicRmwExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
@@ -1444,10 +1481,10 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
case Opcode::I64AtomicRmw8CmpxchgU:
case Opcode::I64AtomicRmw16CmpxchgU:
case Opcode::I64AtomicRmw32CmpxchgU: {
- uint32_t alignment_log2;
+ Address alignment_log2;
CHECK_RESULT(ReadAlignment(&alignment_log2, "memory alignment"));
Address offset;
- CHECK_RESULT(ReadU32Leb128(&offset, "memory offset"));
+ CHECK_RESULT(ReadAddress(&offset, 0, "memory offset"));
CALLBACK(OnAtomicRmwCmpxchgExpr, opcode, alignment_log2, offset);
CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
@@ -1719,15 +1756,32 @@ Result BinaryReader::ReadRelocSection(Offset section_size) {
RelocType type = static_cast<RelocType>(reloc_type);
switch (type) {
case RelocType::MemoryAddressLEB:
+ case RelocType::MemoryAddressLEB64:
case RelocType::MemoryAddressSLEB:
+ case RelocType::MemoryAddressSLEB64:
case RelocType::MemoryAddressRelSLEB:
+ case RelocType::MemoryAddressRelSLEB64:
case RelocType::MemoryAddressI32:
+ case RelocType::MemoryAddressI64:
case RelocType::FunctionOffsetI32:
case RelocType::SectionOffsetI32:
CHECK_RESULT(ReadS32Leb128(&addend, "addend"));
break;
- default:
+
+ case RelocType::FuncIndexLEB:
+ case RelocType::TableIndexSLEB:
+ case RelocType::TableIndexSLEB64:
+ case RelocType::TableIndexI32:
+ case RelocType::TableIndexI64:
+ case RelocType::TypeIndexLEB:
+ case RelocType::GlobalIndexLEB:
+ case RelocType::EventIndexLEB:
+ case RelocType::TableIndexRelSLEB:
break;
+
+ default:
+ PrintError("unknown reloc type: %s", GetRelocTypeName(type));
+ return Result::Error;
}
CALLBACK(OnReloc, type, offset, index, addend);
}
@@ -1841,7 +1895,7 @@ Result BinaryReader::ReadLinkingSection(Offset section_size) {
CALLBACK(OnSegmentInfoCount, count);
for (Index i = 0; i < count; i++) {
string_view name;
- uint32_t alignment_log2;
+ Address alignment_log2;
uint32_t flags;
CHECK_RESULT(ReadStr(&name, "segment name"));
CHECK_RESULT(ReadAlignment(&alignment_log2, "segment alignment"));
diff --git a/src/binary-reader.h b/src/binary-reader.h
index e50f4b9d..9525867a 100644
--- a/src/binary-reader.h
+++ b/src/binary-reader.h
@@ -201,23 +201,23 @@ class BinaryReaderDelegate {
virtual Result OnOpcodeBlockSig(Type sig_type) = 0;
virtual Result OnOpcodeType(Type type) = 0;
virtual Result OnAtomicLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
virtual Result OnAtomicStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
virtual Result OnAtomicRmwExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
virtual Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
virtual Result OnAtomicWaitExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
virtual Result OnAtomicFenceExpr(uint32_t consistency_model) = 0;
virtual Result OnAtomicNotifyExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
virtual Result OnBinaryExpr(Opcode opcode) = 0;
virtual Result OnBlockExpr(Type sig_type) = 0;
@@ -245,7 +245,7 @@ class BinaryReaderDelegate {
virtual Result OnI64ConstExpr(uint64_t value) = 0;
virtual Result OnIfExpr(Type sig_type) = 0;
virtual Result OnLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
virtual Result OnLocalGetExpr(Index local_index) = 0;
virtual Result OnLocalSetExpr(Index local_index) = 0;
@@ -276,7 +276,7 @@ class BinaryReaderDelegate {
Index table_index) = 0;
virtual Result OnSelectExpr(Type result_type) = 0;
virtual Result OnStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
virtual Result OnThrowExpr(Index event_index) = 0;
virtual Result OnTryExpr(Type sig_type) = 0;
@@ -292,7 +292,7 @@ class BinaryReaderDelegate {
virtual Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) = 0;
virtual Result OnLoadSplatExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) = 0;
/* Elem section */
@@ -402,7 +402,7 @@ class BinaryReaderDelegate {
virtual Result OnSegmentInfoCount(Index count) = 0;
virtual Result OnSegmentInfo(Index index,
string_view name,
- uint32_t alignment_log2,
+ Address alignment_log2,
uint32_t flags) = 0;
virtual Result OnInitFunctionCount(Index count) = 0;
virtual Result OnInitFunction(uint32_t priority, Index function_index) = 0;
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index 261190fd..3ad5e53b 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -61,6 +61,7 @@ void WriteType(Stream* stream, Type type, const char* desc) {
void WriteLimits(Stream* stream, const Limits* limits) {
uint32_t flags = limits->has_max ? WABT_BINARY_LIMITS_HAS_MAX_FLAG : 0;
flags |= limits->is_shared ? WABT_BINARY_LIMITS_IS_SHARED_FLAG : 0;
+ flags |= limits->is_64 ? WABT_BINARY_LIMITS_IS_64_FLAG : 0;
WriteU32Leb128(stream, flags, "limits: flags");
WriteU32Leb128(stream, limits->initial, "limits: initial");
if (limits->has_max) {
@@ -824,15 +825,30 @@ void BinaryWriter::WriteRelocSection(const RelocSection* reloc_section) {
WriteU32Leb128(stream_, reloc.index, "reloc index");
switch (reloc.type) {
case RelocType::MemoryAddressLEB:
+ case RelocType::MemoryAddressLEB64:
case RelocType::MemoryAddressSLEB:
+ case RelocType::MemoryAddressSLEB64:
case RelocType::MemoryAddressRelSLEB:
+ case RelocType::MemoryAddressRelSLEB64:
case RelocType::MemoryAddressI32:
+ case RelocType::MemoryAddressI64:
case RelocType::FunctionOffsetI32:
case RelocType::SectionOffsetI32:
WriteU32Leb128(stream_, reloc.addend, "reloc addend");
break;
- default:
+ case RelocType::FuncIndexLEB:
+ case RelocType::TableIndexSLEB:
+ case RelocType::TableIndexSLEB64:
+ case RelocType::TableIndexI32:
+ case RelocType::TableIndexI64:
+ case RelocType::TypeIndexLEB:
+ case RelocType::GlobalIndexLEB:
+ case RelocType::EventIndexLEB:
+ case RelocType::TableIndexRelSLEB:
break;
+ default:
+ fprintf(stderr, "warning: unsupported relocation type: %s\n",
+ GetRelocTypeName(reloc.type));
}
}
diff --git a/src/binary.h b/src/binary.h
index 79ee239d..8132259e 100644
--- a/src/binary.h
+++ b/src/binary.h
@@ -23,8 +23,10 @@
#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_ALL_FLAGS \
- (WABT_BINARY_LIMITS_HAS_MAX_FLAG | WABT_BINARY_LIMITS_IS_SHARED_FLAG)
+#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"
diff --git a/src/common.cc b/src/common.cc
index 1b70bc0d..875f71ae 100644
--- a/src/common.cc
+++ b/src/common.cc
@@ -43,13 +43,16 @@ const char* g_kind_name[] = {"func", "table", "memory", "global", "event"};
WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_kind_name) == kExternalKindCount);
const char* g_reloc_type_name[] = {
- "R_WASM_FUNCTION_INDEX_LEB", "R_WASM_TABLE_INDEX_SLEB",
- "R_WASM_TABLE_INDEX_I32", "R_WASM_MEMORY_ADDR_LEB",
- "R_WASM_MEMORY_ADDR_SLEB", "R_WASM_MEMORY_ADDR_I32",
- "R_WASM_TYPE_INDEX_LEB", "R_WASM_GLOBAL_INDEX_LEB",
- "R_WASM_FUNCTION_OFFSET_I32", "R_WASM_SECTION_OFFSET_I32",
- "R_WASM_EVENT_INDEX_LEB", "R_WASM_MEMORY_ADDR_REL_SLEB",
- "R_WASM_TABLE_INDEX_REL_SLEB",
+ "R_WASM_FUNCTION_INDEX_LEB", "R_WASM_TABLE_INDEX_SLEB",
+ "R_WASM_TABLE_INDEX_I32", "R_WASM_MEMORY_ADDR_LEB",
+ "R_WASM_MEMORY_ADDR_SLEB", "R_WASM_MEMORY_ADDR_I32",
+ "R_WASM_TYPE_INDEX_LEB", "R_WASM_GLOBAL_INDEX_LEB",
+ "R_WASM_FUNCTION_OFFSET_I32", "R_WASM_SECTION_OFFSET_I32",
+ "R_WASM_EVENT_INDEX_LEB", "R_WASM_MEMORY_ADDR_REL_SLEB",
+ "R_WASM_TABLE_INDEX_REL_SLEB", "R_WASM_GLOBAL_INDEX_I32",
+ "R_WASM_MEMORY_ADDR_LEB64", "R_WASM_MEMORY_ADDR_SLEB64",
+ "R_WASM_MEMORY_ADDR_I64", "R_WASM_MEMORY_ADDR_REL_SLEB64",
+ "R_WASM_TABLE_INDEX_SLEB64", "R_WASM_TABLE_INDEX_I64",
};
WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_reloc_type_name) == kRelocTypeCount);
diff --git a/src/common.h b/src/common.h
index 87aee81a..e9060816 100644
--- a/src/common.h
+++ b/src/common.h
@@ -98,7 +98,7 @@
#endif
#define PRIindex "u"
-#define PRIaddress "u"
+#define PRIaddress "lu"
#define PRIoffset PRIzx
struct v128 {
@@ -157,7 +157,7 @@ struct v128 {
namespace wabt {
typedef uint32_t Index; // An index into one of the many index spaces.
-typedef uint32_t Address; // An address or size in linear memory.
+typedef uint64_t Address; // An address or size in linear memory.
typedef size_t Offset; // An offset into a host's file or memory buffer.
static const Address kInvalidAddress = ~0;
@@ -273,22 +273,30 @@ enum SegmentFlags : uint8_t {
};
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 get_global inst
- FunctionOffsetI32 = 8, // e.g. Code offset in DWARF metadata
- SectionOffsetI32 = 9, // e.g. Section offset in DWARF metadata
- EventIndexLEB = 10, // Used in throw instructions
- MemoryAddressRelSLEB = 11, // In PIC code, data address relative to __memory_base
- TableIndexRelSLEB = 12, // In PIC code, table index relative to __table_base
+ 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 get_global inst
+ FunctionOffsetI32 = 8, // e.g. Code offset in DWARF metadata
+ SectionOffsetI32 = 9, // e.g. Section offset in DWARF metadata
+ EventIndexLEB = 10, // Used in throw instructions
+ MemoryAddressRelSLEB =
+ 11, // In PIC code, data address 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
First = FuncIndexLEB,
- Last = TableIndexRelSLEB,
+ Last = TableIndexI64,
};
static const int kRelocTypeCount = WABT_ENUM_COUNT(RelocType);
@@ -360,14 +368,21 @@ struct Limits {
: 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) {}
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 = 0xFFFFFFFF };
+enum { WABT_USE_NATURAL_ALIGNMENT = 0xFFFFFFFFFFFFFFFF };
Result ReadFile(string_view filename, std::vector<uint8_t>* out_data);
diff --git a/src/decompiler.cc b/src/decompiler.cc
index 2de695c2..373d6693 100644
--- a/src/decompiler.cc
+++ b/src/decompiler.cc
@@ -303,7 +303,7 @@ struct Decompiler {
const_exp.etype == ExprType::Const) {
auto& ce = *cast<ConstExpr>(const_exp.e);
if (ce.const_.type() == Type::I32 &&
- (1U << ce.const_.u32()) == align) {
+ (1ULL << ce.const_.u32()) == align) {
// Pfew, case detected :( Lets re-write this in Haskell.
// TODO: we're decompiling these twice.
// The thing to the left of << is going to be part of the index.
diff --git a/src/feature.def b/src/feature.def
index 7e46c2e2..17f4de36 100644
--- a/src/feature.def
+++ b/src/feature.def
@@ -34,3 +34,4 @@ WABT_FEATURE(bulk_memory, "bulk-memory", false, "Bulk-memory
WABT_FEATURE(reference_types, "reference-types", false, "Reference types (externref)")
WABT_FEATURE(annotations, "annotations", false, "Custom annotation syntax")
WABT_FEATURE(gc, "gc", false, "Garbage collection")
+WABT_FEATURE(memory64, "memory64", false, "64-bit memory")
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index 8b44cdaf..9d5eb90c 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -135,23 +135,23 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnOpcode(Opcode Opcode) override;
Result OnAtomicLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicRmwExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicRmwCmpxchgExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicWaitExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnAtomicFenceExpr(uint32_t consistency_model) override;
Result OnAtomicNotifyExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnBinaryExpr(Opcode opcode) override;
Result OnBlockExpr(Type sig_type) override;
@@ -178,7 +178,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnI64ConstExpr(uint64_t value) override;
Result OnIfExpr(Type sig_type) override;
Result OnLoadExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnLocalGetExpr(Index local_index) override;
Result OnLocalSetExpr(Index local_index) override;
@@ -197,7 +197,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnReturnExpr() override;
Result OnSelectExpr(Type result_type) override;
Result OnStoreExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnUnaryExpr(Opcode opcode) override;
Result OnTableCopyExpr(Index dst_index, Index src_index) override;
@@ -214,7 +214,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnSimdLaneOpExpr(Opcode opcode, uint64_t value) override;
Result OnSimdShuffleOpExpr(Opcode opcode, v128 value) override;
Result OnLoadSplatExpr(Opcode opcode,
- uint32_t alignment_log2,
+ Address alignment_log2,
Address offset) override;
Result OnElemSegmentCount(Index count) override;
@@ -894,12 +894,12 @@ Result BinaryReaderInterp::OnSimdShuffleOpExpr(Opcode opcode, v128 value) {
return Result::Ok;
}
-uint32_t GetAlignment(uint32_t alignment_log2) {
+uint32_t GetAlignment(Address alignment_log2) {
return alignment_log2 < 32 ? 1 << alignment_log2 : ~0u;
}
Result BinaryReaderInterp::OnLoadSplatExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(validator_.OnLoadSplat(loc, opcode, GetAlignment(align_log2)));
istream_.Emit(opcode, kMemoryIndex0, offset);
@@ -907,7 +907,7 @@ Result BinaryReaderInterp::OnLoadSplatExpr(Opcode opcode,
}
Result BinaryReaderInterp::OnAtomicLoadExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(validator_.OnAtomicLoad(loc, opcode, GetAlignment(align_log2)));
istream_.Emit(opcode, kMemoryIndex0, offset);
@@ -915,7 +915,7 @@ Result BinaryReaderInterp::OnAtomicLoadExpr(Opcode opcode,
}
Result BinaryReaderInterp::OnAtomicStoreExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(validator_.OnAtomicStore(loc, opcode, GetAlignment(align_log2)));
istream_.Emit(opcode, kMemoryIndex0, offset);
@@ -923,7 +923,7 @@ Result BinaryReaderInterp::OnAtomicStoreExpr(Opcode opcode,
}
Result BinaryReaderInterp::OnAtomicRmwExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(validator_.OnAtomicRmw(loc, opcode, GetAlignment(align_log2)));
istream_.Emit(opcode, kMemoryIndex0, offset);
@@ -931,7 +931,7 @@ Result BinaryReaderInterp::OnAtomicRmwExpr(Opcode opcode,
}
Result BinaryReaderInterp::OnAtomicRmwCmpxchgExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(
validator_.OnAtomicRmwCmpxchg(loc, opcode, GetAlignment(align_log2)));
@@ -1183,7 +1183,7 @@ Result BinaryReaderInterp::OnLocalTeeExpr(Index local_index) {
}
Result BinaryReaderInterp::OnLoadExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(validator_.OnLoad(loc, opcode, GetAlignment(align_log2)));
istream_.Emit(opcode, kMemoryIndex0, offset);
@@ -1191,7 +1191,7 @@ Result BinaryReaderInterp::OnLoadExpr(Opcode opcode,
}
Result BinaryReaderInterp::OnStoreExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(validator_.OnStore(loc, opcode, GetAlignment(align_log2)));
istream_.Emit(opcode, kMemoryIndex0, offset);
@@ -1273,7 +1273,7 @@ Result BinaryReaderInterp::OnUnreachableExpr() {
}
Result BinaryReaderInterp::OnAtomicWaitExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(validator_.OnAtomicWait(loc, opcode, GetAlignment(align_log2)));
istream_.Emit(opcode, kMemoryIndex0, offset);
@@ -1287,7 +1287,7 @@ Result BinaryReaderInterp::OnAtomicFenceExpr(uint32_t consistency_model) {
}
Result BinaryReaderInterp::OnAtomicNotifyExpr(Opcode opcode,
- uint32_t align_log2,
+ Address align_log2,
Address offset) {
CHECK_RESULT(
validator_.OnAtomicNotify(loc, opcode, GetAlignment(align_log2)));
diff --git a/src/interp/interp-inl.h b/src/interp/interp-inl.h
index 0d306ebe..ab755bbc 100644
--- a/src/interp/interp-inl.h
+++ b/src/interp/interp-inl.h
@@ -631,19 +631,19 @@ inline Memory::Ptr Memory::New(interp::Store& store, MemoryType type) {
return store.Alloc<Memory>(store, type);
}
-inline bool Memory::IsValidAccess(u32 offset, u32 addend, size_t size) const {
- return u64{offset} + addend + size <= data_.size();
+inline bool Memory::IsValidAccess(u64 offset, u64 addend, u64 size) const {
+ return offset + addend + size <= data_.size();
}
-inline bool Memory::IsValidAtomicAccess(u32 offset,
- u32 addend,
- size_t size) const {
+inline bool Memory::IsValidAtomicAccess(u64 offset,
+ u64 addend,
+ u64 size) const {
return IsValidAccess(offset, addend, size) &&
((offset + addend) & (size - 1)) == 0;
}
template <typename T>
-Result Memory::Load(u32 offset, u32 addend, T* out) const {
+Result Memory::Load(u64 offset, u64 addend, T* out) const {
if (!IsValidAccess(offset, addend, sizeof(T))) {
return Result::Error;
}
@@ -652,7 +652,7 @@ Result Memory::Load(u32 offset, u32 addend, T* out) const {
}
template <typename T>
-T WABT_VECTORCALL Memory::UnsafeLoad(u32 offset, u32 addend) const {
+T WABT_VECTORCALL Memory::UnsafeLoad(u64 offset, u64 addend) const {
assert(IsValidAccess(offset, addend, sizeof(T)));
T val;
memcpy(&val, data_.data() + offset + addend, sizeof(T));
@@ -660,7 +660,7 @@ T WABT_VECTORCALL Memory::UnsafeLoad(u32 offset, u32 addend) const {
}
template <typename T>
-Result WABT_VECTORCALL Memory::Store(u32 offset, u32 addend, T val) {
+Result WABT_VECTORCALL Memory::Store(u64 offset, u64 addend, T val) {
if (!IsValidAccess(offset, addend, sizeof(T))) {
return Result::Error;
}
@@ -669,7 +669,7 @@ Result WABT_VECTORCALL Memory::Store(u32 offset, u32 addend, T val) {
}
template <typename T>
-Result Memory::AtomicLoad(u32 offset, u32 addend, T* out) const {
+Result Memory::AtomicLoad(u64 offset, u64 addend, T* out) const {
if (!IsValidAtomicAccess(offset, addend, sizeof(T))) {
return Result::Error;
}
@@ -678,7 +678,7 @@ Result Memory::AtomicLoad(u32 offset, u32 addend, T* out) const {
}
template <typename T>
-Result Memory::AtomicStore(u32 offset, u32 addend, T val) {
+Result Memory::AtomicStore(u64 offset, u64 addend, T val) {
if (!IsValidAtomicAccess(offset, addend, sizeof(T))) {
return Result::Error;
}
@@ -687,7 +687,7 @@ Result Memory::AtomicStore(u32 offset, u32 addend, T val) {
}
template <typename T, typename F>
-Result Memory::AtomicRmw(u32 offset, u32 addend, T rhs, F&& func, T* out) {
+Result Memory::AtomicRmw(u64 offset, u64 addend, T rhs, F&& func, T* out) {
T lhs;
CHECK_RESULT(AtomicLoad(offset, addend, &lhs));
CHECK_RESULT(AtomicStore(offset, addend, func(lhs, rhs)));
@@ -696,8 +696,8 @@ Result Memory::AtomicRmw(u32 offset, u32 addend, T rhs, F&& func, T* out) {
}
template <typename T>
-Result Memory::AtomicRmwCmpxchg(u32 offset,
- u32 addend,
+Result Memory::AtomicRmwCmpxchg(u64 offset,
+ u64 addend,
T expect,
T replace,
T* out) {
@@ -714,11 +714,11 @@ inline u8* Memory::UnsafeData() {
return data_.data();
}
-inline u32 Memory::ByteSize() const {
+inline u64 Memory::ByteSize() const {
return data_.size();
}
-inline u32 Memory::PageSize() const {
+inline u64 Memory::PageSize() const {
return pages_;
}
@@ -822,7 +822,7 @@ inline const DataDesc& DataSegment::desc() const {
return *desc_;
}
-inline u32 DataSegment::size() const {
+inline u64 DataSegment::size() const {
return size_;
}
diff --git a/src/interp/interp.cc b/src/interp/interp.cc
index 7aee6012..6ea80279 100644
--- a/src/interp/interp.cc
+++ b/src/interp/interp.cc
@@ -169,7 +169,8 @@ Result Match(const EventType& expected,
}
//// Limits ////
-bool CanGrow(const Limits& limits, u32 old_size, u32 delta, u32* new_size) {
+template <typename T>
+bool CanGrow(const Limits& limits, T old_size, T delta, T* new_size) {
if (limits.max >= delta && old_size <= limits.max - delta) {
*new_size = old_size + delta;
return true;
@@ -456,7 +457,7 @@ Result Table::Grow(Store& store, u32 count, Ref ref) {
size_t old_size = elements_.size();
u32 new_size;
if (store.HasValueType(ref, type_.element) &&
- CanGrow(type_.limits, old_size, count, &new_size)) {
+ CanGrow<u32>(type_.limits, old_size, count, &new_size)) {
elements_.resize(new_size);
Fill(store, old_size, ref, new_size - old_size);
return Result::Ok;
@@ -527,9 +528,9 @@ Result Memory::Match(class Store& store,
return MatchImpl(store, import_type, type_, out_trap);
}
-Result Memory::Grow(u32 count) {
- u32 new_pages;
- if (CanGrow(type_.limits, pages_, count, &new_pages)) {
+Result Memory::Grow(u64 count) {
+ u64 new_pages;
+ if (CanGrow<u64>(type_.limits, pages_, count, &new_pages)) {
pages_ = new_pages;
data_.resize(new_pages * WABT_PAGE_SIZE);
return Result::Ok;
@@ -537,7 +538,7 @@ Result Memory::Grow(u32 count) {
return Result::Error;
}
-Result Memory::Fill(u32 offset, u8 value, u32 size) {
+Result Memory::Fill(u64 offset, u8 value, u64 size) {
if (IsValidAccess(offset, 0, size)) {
std::fill(data_.begin() + offset, data_.begin() + offset + size, value);
return Result::Ok;
@@ -545,10 +546,10 @@ Result Memory::Fill(u32 offset, u8 value, u32 size) {
return Result::Error;
}
-Result Memory::Init(u32 dst_offset,
+Result Memory::Init(u64 dst_offset,
const DataSegment& src,
- u32 src_offset,
- u32 size) {
+ u64 src_offset,
+ u64 size) {
if (IsValidAccess(dst_offset, 0, size) &&
src.IsValidRange(src_offset, size)) {
std::copy(src.desc().data.begin() + src_offset,
@@ -561,10 +562,10 @@ Result Memory::Init(u32 dst_offset,
// static
Result Memory::Copy(Memory& dst,
- u32 dst_offset,
+ u64 dst_offset,
const Memory& src,
- u32 src_offset,
- u32 size) {
+ u64 src_offset,
+ u64 size) {
if (dst.IsValidAccess(dst_offset, 0, size) &&
src.IsValidAccess(src_offset, 0, size)) {
auto src_begin = src.data_.begin() + src_offset;
@@ -673,8 +674,8 @@ bool ElemSegment::IsValidRange(u32 offset, u32 size) const {
DataSegment::DataSegment(const DataDesc* desc)
: desc_(desc), size_(desc->data.size()) {}
-bool DataSegment::IsValidRange(u32 offset, u32 size) const {
- u32 data_size = size_;
+bool DataSegment::IsValidRange(u64 offset, u64 size) const {
+ u64 data_size = size_;
return size <= data_size && offset <= data_size - size;
}
@@ -1175,17 +1176,29 @@ RunResult Thread::StepInternal(Trap::Ptr* out_trap) {
case O::MemorySize: {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
- Push(memory->PageSize());
+ if (memory->type().limits.is_64) {
+ Push<u64>(memory->PageSize());
+ } else {
+ Push<u32>(static_cast<u32>(memory->PageSize()));
+ }
break;
}
case O::MemoryGrow: {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32]};
- u32 old_size = memory->PageSize();
+ u64 old_size = memory->PageSize();
if (Failed(memory->Grow(Pop<u32>()))) {
- Push<s32>(-1);
+ if (memory->type().limits.is_64) {
+ Push<s64>(-1);
+ } else {
+ Push<s32>(-1);
+ }
} else {
- Push<u32>(old_size);
+ if (memory->type().limits.is_64) {
+ Push<u64>(old_size);
+ } else {
+ Push<u32>(old_size);
+ }
}
break;
}
@@ -1724,11 +1737,11 @@ RunResult Thread::DoCall(const Func::Ptr& func, Trap::Ptr* out_trap) {
template <typename T>
RunResult Thread::Load(Instr instr, T* out, Trap::Ptr* out_trap) {
Memory::Ptr memory{store_, inst_->memories()[instr.imm_u32x2.fst]};
- u32 offset = Pop<u32>();
+ u64 offset = memory->type().limits.is_64 ? Pop<u64>() : Pop<u32>();
TRAP_IF(Failed(memory->Load(offset, instr.imm_u32x2.snd, out)),
StringPrintf("out of bounds memory access: access at %" PRIu64
"+%" PRIzd " >= max value %u",
- u64{offset} + instr.imm_u32x2.snd, sizeof(T),
+ offset + instr.imm_u32x2.snd, sizeof(T),
memory->ByteSize()));
return RunResult::Ok;
}
diff --git a/src/interp/interp.h b/src/interp/interp.h
index 8ebd43df..dcdaaa50 100644
--- a/src/interp/interp.h
+++ b/src/interp/interp.h
@@ -782,38 +782,38 @@ class Memory : public Extern {
Result Match(Store&, const ImportType&, Trap::Ptr* out_trap) override;
- bool IsValidAccess(u32 offset, u32 addend, size_t size) const;
- bool IsValidAtomicAccess(u32 offset, u32 addend, size_t size) const;
+ bool IsValidAccess(u64 offset, u64 addend, u64 size) const;
+ bool IsValidAtomicAccess(u64 offset, u64 addend, u64 size) const;
template <typename T>
- Result Load(u32 offset, u32 addend, T* out) const;
+ Result Load(u64 offset, u64 addend, T* out) const;
template <typename T>
- Result WABT_VECTORCALL Store(u32 offset, u32 addend, T);
- Result Grow(u32 pages);
- Result Fill(u32 offset, u8 value, u32 size);
- Result Init(u32 dst_offset, const DataSegment&, u32 src_offset, u32 size);
+ Result WABT_VECTORCALL Store(u64 offset, u64 addend, T);
+ Result Grow(u64 pages);
+ Result Fill(u64 offset, u8 value, u64 size);
+ Result Init(u64 dst_offset, const DataSegment&, u64 src_offset, u64 size);
static Result Copy(Memory& dst,
- u32 dst_offset,
+ u64 dst_offset,
const Memory& src,
- u32 src_offset,
- u32 size);
+ u64 src_offset,
+ u64 size);
// Fake atomics; just checks alignment.
template <typename T>
- Result AtomicLoad(u32 offset, u32 addend, T* out) const;
+ Result AtomicLoad(u64 offset, u64 addend, T* out) const;
template <typename T>
- Result AtomicStore(u32 offset, u32 addend, T);
+ Result AtomicStore(u64 offset, u64 addend, T);
template <typename T, typename F>
- Result AtomicRmw(u32 offset, u32 addend, T, F&& func, T* out);
+ Result AtomicRmw(u64 offset, u64 addend, T, F&& func, T* out);
template <typename T>
- Result AtomicRmwCmpxchg(u32 offset, u32 addend, T expect, T replace, T* out);
+ Result AtomicRmwCmpxchg(u64 offset, u64 addend, T expect, T replace, T* out);
- u32 ByteSize() const;
- u32 PageSize() const;
+ u64 ByteSize() const;
+ u64 PageSize() const;
// Unsafe API.
template <typename T>
- T WABT_VECTORCALL UnsafeLoad(u32 offset, u32 addend) const;
+ T WABT_VECTORCALL UnsafeLoad(u64 offset, u64 addend) const;
u8* UnsafeData();
const ExternType& extern_type() override;
@@ -826,7 +826,7 @@ class Memory : public Extern {
MemoryType type_;
Buffer data_;
- u32 pages_;
+ u64 pages_;
};
class Global : public Extern {
@@ -908,15 +908,15 @@ class DataSegment {
public:
explicit DataSegment(const DataDesc*);
- bool IsValidRange(u32 offset, u32 size) const;
+ bool IsValidRange(u64 offset, u64 size) const;
void Drop();
const DataDesc& desc() const;
- u32 size() const;
+ u64 size() const;
private:
const DataDesc* desc_; // Borrowed from the Module.
- u32 size_;
+ u64 size_;
};
class Module : public Object {
diff --git a/src/ir.h b/src/ir.h
index 9b456a7b..cb155454 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -586,7 +586,7 @@ class LoadStoreExpr : public ExprMixin<TypeEnum> {
public:
LoadStoreExpr(Opcode opcode,
Address align,
- uint32_t offset,
+ Address offset,
const Location& loc = Location())
: ExprMixin<TypeEnum>(loc),
opcode(opcode),
@@ -595,7 +595,7 @@ class LoadStoreExpr : public ExprMixin<TypeEnum> {
Opcode opcode;
Address align;
- uint32_t offset;
+ Address offset;
};
typedef LoadStoreExpr<ExprType::Load> LoadExpr;
diff --git a/src/leb128.cc b/src/leb128.cc
index 796c4e29..c3decac5 100644
--- a/src/leb128.cc
+++ b/src/leb128.cc
@@ -187,6 +187,50 @@ size_t ReadU32Leb128(const uint8_t* p,
}
}
+size_t ReadU64Leb128(const uint8_t* p,
+ const uint8_t* end,
+ uint64_t* out_value) {
+ if (p < end && (p[0] & 0x80) == 0) {
+ *out_value = LEB128_1(uint64_t);
+ return 1;
+ } else if (p + 1 < end && (p[1] & 0x80) == 0) {
+ *out_value = LEB128_2(uint64_t);
+ return 2;
+ } else if (p + 2 < end && (p[2] & 0x80) == 0) {
+ *out_value = LEB128_3(uint64_t);
+ return 3;
+ } else if (p + 3 < end && (p[3] & 0x80) == 0) {
+ *out_value = LEB128_4(uint64_t);
+ return 4;
+ } else if (p + 4 < end && (p[4] & 0x80) == 0) {
+ *out_value = LEB128_5(uint64_t);
+ return 5;
+ } else if (p + 5 < end && (p[5] & 0x80) == 0) {
+ *out_value = LEB128_6(uint64_t);
+ return 6;
+ } else if (p + 6 < end && (p[6] & 0x80) == 0) {
+ *out_value = LEB128_7(uint64_t);
+ return 7;
+ } else if (p + 7 < end && (p[7] & 0x80) == 0) {
+ *out_value = LEB128_8(uint64_t);
+ return 8;
+ } else if (p + 8 < end && (p[8] & 0x80) == 0) {
+ *out_value = LEB128_9(uint64_t);
+ return 9;
+ } else if (p + 9 < end && (p[9] & 0x80) == 0) {
+ // The top bits set represent values > 32 bits.
+ if (p[9] & 0xf0) {
+ return 0;
+ }
+ *out_value = LEB128_10(uint64_t);
+ return 10;
+ } else {
+ // past the end.
+ *out_value = 0;
+ return 0;
+ }
+}
+
size_t ReadS32Leb128(const uint8_t* p,
const uint8_t* end,
uint32_t* out_value) {
diff --git a/src/leb128.h b/src/leb128.h
index 33eb544a..4ec74774 100644
--- a/src/leb128.h
+++ b/src/leb128.h
@@ -59,6 +59,7 @@ void WriteS32Leb128(Stream* stream, T value, const char* 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);
diff --git a/src/opcode.h b/src/opcode.h
index d96c08e7..94cd4cb8 100644
--- a/src/opcode.h
+++ b/src/opcode.h
@@ -69,6 +69,14 @@ struct Opcode {
Type GetParamType(int n) const { return GetInfo().param_types[n - 1]; }
Address GetMemorySize() const { return GetInfo().memory_size; }
+ // If this is a load/store op, the type depends on the memory used.
+ Type GetMemoryParam(Type param,
+ const Limits* limits,
+ bool has_address_operands) {
+ return limits && limits->is_64 && has_address_operands ? Type(Type::I64)
+ : param;
+ }
+
// Get the byte sequence for this opcode, including prefix.
std::vector<uint8_t> GetBytes() const;
diff --git a/src/shared-validator.cc b/src/shared-validator.cc
index 8b6bef80..5f429e59 100644
--- a/src/shared-validator.cc
+++ b/src/shared-validator.cc
@@ -612,10 +612,11 @@ Result SharedValidator::OnAtomicLoad(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAtomicAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnAtomicLoad(opcode);
+ result |= typechecker_.OnAtomicLoad(opcode, mt.limits);
return result;
}
@@ -623,10 +624,11 @@ Result SharedValidator::OnAtomicNotify(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAtomicAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnAtomicNotify(opcode);
+ result |= typechecker_.OnAtomicNotify(opcode, mt.limits);
return result;
}
@@ -634,10 +636,11 @@ Result SharedValidator::OnAtomicRmwCmpxchg(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAtomicAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnAtomicRmwCmpxchg(opcode);
+ result |= typechecker_.OnAtomicRmwCmpxchg(opcode, mt.limits);
return result;
}
@@ -645,10 +648,11 @@ Result SharedValidator::OnAtomicRmw(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAtomicAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnAtomicRmw(opcode);
+ result |= typechecker_.OnAtomicRmw(opcode, mt.limits);
return result;
}
@@ -656,10 +660,11 @@ Result SharedValidator::OnAtomicStore(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAtomicAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnAtomicStore(opcode);
+ result |= typechecker_.OnAtomicStore(opcode, mt.limits);
return result;
}
@@ -667,10 +672,11 @@ Result SharedValidator::OnAtomicWait(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAtomicAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnAtomicWait(opcode);
+ result |= typechecker_.OnAtomicWait(opcode, mt.limits);
return result;
}
@@ -859,10 +865,11 @@ Result SharedValidator::OnLoad(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnLoad(opcode);
+ result |= typechecker_.OnLoad(opcode, mt.limits);
return result;
}
@@ -870,10 +877,11 @@ Result SharedValidator::OnLoadSplat(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnLoad(opcode);
+ result |= typechecker_.OnLoad(opcode, mt.limits);
return result;
}
@@ -916,42 +924,47 @@ Result SharedValidator::OnLoop(const Location& loc, Type sig_type) {
Result SharedValidator::OnMemoryCopy(const Location& loc) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
- result |= typechecker_.OnMemoryCopy();
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= typechecker_.OnMemoryCopy(mt.limits);
return result;
}
Result SharedValidator::OnMemoryFill(const Location& loc) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
- result |= typechecker_.OnMemoryFill();
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= typechecker_.OnMemoryFill(mt.limits);
return result;
}
Result SharedValidator::OnMemoryGrow(const Location& loc) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
- result |= typechecker_.OnMemoryGrow();
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= typechecker_.OnMemoryGrow(mt.limits);
return result;
}
Result SharedValidator::OnMemoryInit(const Location& loc, Var segment_var) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckDataSegmentIndex(segment_var);
- result |= typechecker_.OnMemoryInit(segment_var.index());
+ result |= typechecker_.OnMemoryInit(segment_var.index(), mt.limits);
return result;
}
Result SharedValidator::OnMemorySize(const Location& loc) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
- result |= typechecker_.OnMemorySize();
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= typechecker_.OnMemorySize(mt.limits);
return result;
}
@@ -1047,10 +1060,11 @@ Result SharedValidator::OnStore(const Location& loc,
Opcode opcode,
Address alignment) {
Result result = Result::Ok;
+ MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc));
+ result |= CheckMemoryIndex(Var(0, loc), &mt);
result |= CheckAlign(loc, alignment, opcode.GetMemorySize());
- result |= typechecker_.OnStore(opcode);
+ result |= typechecker_.OnStore(opcode, mt.limits);
return result;
}
diff --git a/src/type-checker.cc b/src/type-checker.cc
index 5526640a..f9528344 100644
--- a/src/type-checker.cc
+++ b/src/type-checker.cc
@@ -255,23 +255,42 @@ Result TypeChecker::PopAndCheck3Types(Type expected1,
return result;
}
-Result TypeChecker::CheckOpcode1(Opcode opcode) {
- Result result = PopAndCheck1Type(opcode.GetParamType1(), opcode.GetName());
- PushType(opcode.GetResultType());
+Result TypeChecker::CheckOpcode1(Opcode opcode,
+ const Limits* limits,
+ bool has_address_operands) {
+ Result result =
+ PopAndCheck1Type(opcode.GetMemoryParam(
+ opcode.GetParamType1(), limits,
+ has_address_operands || opcode.GetMemorySize() != 0),
+ opcode.GetName());
+ PushType(has_address_operands
+ ? opcode.GetMemoryParam(opcode.GetResultType(), limits, true)
+ : opcode.GetResultType());
return result;
}
-Result TypeChecker::CheckOpcode2(Opcode opcode) {
- Result result = PopAndCheck2Types(opcode.GetParamType1(),
- opcode.GetParamType2(), opcode.GetName());
+Result TypeChecker::CheckOpcode2(Opcode opcode, const Limits* limits) {
+ Result result =
+ PopAndCheck2Types(opcode.GetMemoryParam(opcode.GetParamType1(), limits,
+ opcode.GetMemorySize() != 0),
+ opcode.GetParamType2(), opcode.GetName());
PushType(opcode.GetResultType());
return result;
}
-Result TypeChecker::CheckOpcode3(Opcode opcode) {
+Result TypeChecker::CheckOpcode3(Opcode opcode,
+ const Limits* limits1,
+ const Limits* limits2,
+ const Limits* limits3) {
+ bool has_address_operands = limits1 || limits2 || limits3;
Result result =
- PopAndCheck3Types(opcode.GetParamType1(), opcode.GetParamType2(),
- opcode.GetParamType3(), opcode.GetName());
+ PopAndCheck3Types(opcode.GetMemoryParam(opcode.GetParamType1(), limits1,
+ has_address_operands),
+ opcode.GetMemoryParam(opcode.GetParamType2(), limits2,
+ has_address_operands),
+ opcode.GetMemoryParam(opcode.GetParamType3(), limits3,
+ has_address_operands),
+ opcode.GetName());
PushType(opcode.GetResultType());
return result;
}
@@ -331,32 +350,32 @@ Result TypeChecker::BeginFunction(const TypeVector& sig) {
return Result::Ok;
}
-Result TypeChecker::OnAtomicLoad(Opcode opcode) {
- return CheckOpcode1(opcode);
+Result TypeChecker::OnAtomicLoad(Opcode opcode, const Limits& limits) {
+ return CheckOpcode1(opcode, &limits);
}
-Result TypeChecker::OnAtomicStore(Opcode opcode) {
- return CheckOpcode2(opcode);
+Result TypeChecker::OnAtomicStore(Opcode opcode, const Limits& limits) {
+ return CheckOpcode2(opcode, &limits);
}
-Result TypeChecker::OnAtomicRmw(Opcode opcode) {
- return CheckOpcode2(opcode);
+Result TypeChecker::OnAtomicRmw(Opcode opcode, const Limits& limits) {
+ return CheckOpcode2(opcode, &limits);
}
-Result TypeChecker::OnAtomicRmwCmpxchg(Opcode opcode) {
- return CheckOpcode3(opcode);
+Result TypeChecker::OnAtomicRmwCmpxchg(Opcode opcode, const Limits& limits) {
+ return CheckOpcode3(opcode, &limits);
}
-Result TypeChecker::OnAtomicWait(Opcode opcode) {
- return CheckOpcode3(opcode);
+Result TypeChecker::OnAtomicWait(Opcode opcode, const Limits& limits) {
+ return CheckOpcode3(opcode, &limits);
}
Result TypeChecker::OnAtomicFence(uint32_t consistency_model) {
return Result::Ok;
}
-Result TypeChecker::OnAtomicNotify(Opcode opcode) {
- return CheckOpcode2(opcode);
+Result TypeChecker::OnAtomicNotify(Opcode opcode, const Limits& limits) {
+ return CheckOpcode2(opcode, &limits);
}
Result TypeChecker::OnBinary(Opcode opcode) {
@@ -570,8 +589,8 @@ Result TypeChecker::OnGlobalSet(Type type) {
return PopAndCheck1Type(type, "global.set");
}
-Result TypeChecker::OnLoad(Opcode opcode) {
- return CheckOpcode1(opcode);
+Result TypeChecker::OnLoad(Opcode opcode, const Limits& limits) {
+ return CheckOpcode1(opcode, &limits);
}
Result TypeChecker::OnLocalGet(Type type) {
@@ -598,28 +617,28 @@ Result TypeChecker::OnLoop(const TypeVector& param_types,
return result;
}
-Result TypeChecker::OnMemoryCopy() {
- return CheckOpcode3(Opcode::MemoryCopy);
+Result TypeChecker::OnMemoryCopy(const Limits& limits) {
+ return CheckOpcode3(Opcode::MemoryCopy, &limits, &limits, &limits);
}
Result TypeChecker::OnDataDrop(uint32_t segment) {
return Result::Ok;
}
-Result TypeChecker::OnMemoryFill() {
- return CheckOpcode3(Opcode::MemoryFill);
+Result TypeChecker::OnMemoryFill(const Limits& limits) {
+ return CheckOpcode3(Opcode::MemoryFill, &limits, nullptr, &limits);
}
-Result TypeChecker::OnMemoryGrow() {
- return CheckOpcode1(Opcode::MemoryGrow);
+Result TypeChecker::OnMemoryGrow(const Limits& limits) {
+ return CheckOpcode1(Opcode::MemoryGrow, &limits, true);
}
-Result TypeChecker::OnMemoryInit(uint32_t segment) {
- return CheckOpcode3(Opcode::MemoryInit);
+Result TypeChecker::OnMemoryInit(uint32_t segment, const Limits& limits) {
+ return CheckOpcode3(Opcode::MemoryInit, &limits);
}
-Result TypeChecker::OnMemorySize() {
- PushType(Type::I32);
+Result TypeChecker::OnMemorySize(const Limits& limits) {
+ PushType(limits.is_64 ? Type::I64 : Type::I32);
return Result::Ok;
}
@@ -736,8 +755,8 @@ Result TypeChecker::OnSelect(Type expected) {
return result;
}
-Result TypeChecker::OnStore(Opcode opcode) {
- return CheckOpcode2(opcode);
+Result TypeChecker::OnStore(Opcode opcode, const Limits& limits) {
+ return CheckOpcode2(opcode, &limits);
}
Result TypeChecker::OnTry(const TypeVector& param_types,
diff --git a/src/type-checker.h b/src/type-checker.h
index 00edef41..1225ff18 100644
--- a/src/type-checker.h
+++ b/src/type-checker.h
@@ -60,12 +60,12 @@ class TypeChecker {
Result BeginFunction(const TypeVector& sig);
Result OnAtomicFence(uint32_t consistency_model);
- Result OnAtomicLoad(Opcode);
- Result OnAtomicNotify(Opcode);
- Result OnAtomicStore(Opcode);
- Result OnAtomicRmw(Opcode);
- Result OnAtomicRmwCmpxchg(Opcode);
- Result OnAtomicWait(Opcode);
+ 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);
@@ -89,17 +89,17 @@ class TypeChecker {
Result OnGlobalGet(Type);
Result OnGlobalSet(Type);
Result OnIf(const TypeVector& param_types, const TypeVector& result_types);
- Result OnLoad(Opcode);
+ 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();
+ Result OnMemoryCopy(const Limits& limits);
Result OnDataDrop(Index);
- Result OnMemoryFill();
- Result OnMemoryGrow();
- Result OnMemoryInit(Index);
- Result OnMemorySize();
+ 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);
@@ -116,7 +116,7 @@ class TypeChecker {
Result OnSelect(Type expected);
Result OnSimdLaneOp(Opcode, uint64_t);
Result OnSimdShuffleOp(Opcode, v128);
- Result OnStore(Opcode);
+ Result OnStore(Opcode, const Limits& limits);
Result OnTernary(Opcode);
Result OnThrow(const TypeVector& sig);
Result OnTry(const TypeVector& param_types, const TypeVector& result_types);
@@ -150,15 +150,20 @@ class TypeChecker {
Result PopAndCheckCall(const TypeVector& param_types,
const TypeVector& result_types,
const char* desc);
- Result PopAndCheck1Type(Type expected, 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);
- Result CheckOpcode2(Opcode opcode);
- Result CheckOpcode3(Opcode opcode);
+ Result CheckOpcode1(Opcode opcode,
+ const Limits* limits = nullptr,
+ bool has_address_operands = false);
+ 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>
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index 64ac4c82..8d7243fb 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -894,7 +894,7 @@ Result WastParser::ParseQuotedText(std::string* text) {
return Result::Ok;
}
-bool WastParser::ParseOffsetOpt(uint32_t* out_offset) {
+bool WastParser::ParseOffsetOpt(Address* out_offset) {
WABT_TRACE(ParseOffsetOpt);
if (PeekMatch(TokenType::OffsetEqNat)) {
Token token = Consume();
@@ -905,11 +905,11 @@ bool WastParser::ParseOffsetOpt(uint32_t* out_offset) {
Error(token.loc, "invalid offset \"" PRIstringview "\"",
WABT_PRINTF_STRING_VIEW_ARG(sv));
}
+ // FIXME: make this depend on the current memory.
if (offset64 > UINT32_MAX) {
Error(token.loc, "offset must be less than or equal to 0xffffffff");
}
-
- *out_offset = static_cast<uint32_t>(offset64);
+ *out_offset = offset64;
return true;
} else {
*out_offset = 0;
@@ -917,12 +917,12 @@ bool WastParser::ParseOffsetOpt(uint32_t* out_offset) {
}
}
-bool WastParser::ParseAlignOpt(uint32_t* out_align) {
+bool WastParser::ParseAlignOpt(Address* out_align) {
WABT_TRACE(ParseAlignOpt);
if (PeekMatch(TokenType::AlignEqNat)) {
Token token = Consume();
string_view sv = token.text();
- if (Failed(ParseInt32(sv.begin(), sv.end(), out_align,
+ if (Failed(ParseInt64(sv.begin(), sv.end(), out_align,
ParseIntType::UnsignedOnly))) {
Error(token.loc, "invalid alignment \"" PRIstringview "\"",
WABT_PRINTF_STRING_VIEW_ARG(sv));
@@ -954,6 +954,11 @@ Result WastParser::ParseLimits(Limits* out_limits) {
out_limits->is_shared = true;
}
+ if (PeekMatch(TokenType::ValueType) && GetToken().type() == Type::I64) {
+ Consume();
+ out_limits->is_64 = true;
+ }
+
return Result::Ok;
}
@@ -1717,8 +1722,8 @@ Result WastParser::ParsePlainLoadStoreInstr(Location loc,
Token token,
std::unique_ptr<Expr>* out_expr) {
Opcode opcode = token.opcode();
- uint32_t offset;
- uint32_t align;
+ Address offset;
+ Address align;
ParseOffsetOpt(&offset);
ParseAlignOpt(&align);
out_expr->reset(new T(opcode, align, offset, loc));
diff --git a/src/wast-parser.h b/src/wast-parser.h
index 4fa693cf..57c0264f 100644
--- a/src/wast-parser.h
+++ b/src/wast-parser.h
@@ -135,8 +135,8 @@ class WastParser {
Result ParseRefType(Type* out_type);
bool ParseRefTypeOpt(Type* out_type);
Result ParseQuotedText(std::string* text);
- bool ParseOffsetOpt(uint32_t* offset);
- bool ParseAlignOpt(uint32_t* align);
+ bool ParseOffsetOpt(Address* offset);
+ bool ParseAlignOpt(Address* align);
Result ParseLimits(Limits*);
Result ParseNat(uint64_t*);
diff --git a/src/wat-writer.cc b/src/wat-writer.cc
index 837f109e..ea46d802 100644
--- a/src/wat-writer.cc
+++ b/src/wat-writer.cc
@@ -1274,6 +1274,9 @@ void WatWriter::WriteLimits(const Limits& limits) {
if (limits.is_shared) {
Writef("shared");
}
+ if (limits.is_64) {
+ Writef("i64");
+ }
}
void WatWriter::WriteTable(const Table& table) {
diff --git a/test/binary/bad-memory-limits-flag.txt b/test/binary/bad-memory-limits-flag.txt
index cf9bd1d6..3e8922b8 100644
--- a/test/binary/bad-memory-limits-flag.txt
+++ b/test/binary/bad-memory-limits-flag.txt
@@ -3,9 +3,9 @@ magic
version
section(MEMORY) {
count[1]
- flags[4]
+ flags[8]
}
(;; STDERR ;;;
-000000c: error: malformed memory limits flag: 4
-000000c: error: malformed memory limits flag: 4
+000000c: error: malformed memory limits flag: 8
+000000c: error: malformed memory limits flag: 8
;;; STDERR ;;)
diff --git a/test/binary/bad-table-limits-flag.txt b/test/binary/bad-table-limits-flag.txt
index 5bfb474d..28f6b438 100644
--- a/test/binary/bad-table-limits-flag.txt
+++ b/test/binary/bad-table-limits-flag.txt
@@ -4,9 +4,9 @@ version
section(TABLE) {
count[1]
anyfunc
- flags[4]
+ flags[8]
}
(;; STDERR ;;;
-000000d: error: malformed table limits flag: 4
-000000d: error: malformed table limits flag: 4
+000000d: error: malformed table limits flag: 8
+000000d: error: malformed table limits flag: 8
;;; STDERR ;;)
diff --git a/test/dump/bulk-memory64.txt b/test/dump/bulk-memory64.txt
new file mode 100644
index 00000000..b473faf7
--- /dev/null
+++ b/test/dump/bulk-memory64.txt
@@ -0,0 +1,54 @@
+;;; TOOL: run-objdump
+;;; ARGS0: --enable-bulk-memory
+
+(module
+ (memory 1 i64)
+ (data "a")
+ (func
+ i64.const 0 i32.const 0 i32.const 0 memory.init 0
+ data.drop 0
+ i64.const 0 i64.const 0 i64.const 0 memory.copy
+ i64.const 0 i32.const 0 i64.const 0 memory.fill
+ )
+
+ (table 1 anyfunc)
+ (elem func 0)
+ (func
+ i32.const 0 i32.const 0 i32.const 0 table.init 0
+ elem.drop 0
+ i32.const 0 i32.const 0 i32.const 0 table.copy
+ )
+)
+(;; STDOUT ;;;
+
+bulk-memory64.wasm: file format wasm 0x1
+
+Code Disassembly:
+
+00002c func[0]:
+ 00002d: 42 00 | i64.const 0
+ 00002f: 41 00 | i32.const 0
+ 000031: 41 00 | i32.const 0
+ 000033: fc 08 00 00 | memory.init 0 0
+ 000037: fc 09 00 | data.drop 0
+ 00003a: 42 00 | i64.const 0
+ 00003c: 42 00 | i64.const 0
+ 00003e: 42 00 | i64.const 0
+ 000040: fc 0a 00 00 | memory.copy 0 0
+ 000044: 42 00 | i64.const 0
+ 000046: 41 00 | i32.const 0
+ 000048: 42 00 | i64.const 0
+ 00004a: fc 0b 00 | memory.fill 0
+ 00004d: 0b | end
+00004f func[1]:
+ 000050: 41 00 | i32.const 0
+ 000052: 41 00 | i32.const 0
+ 000054: 41 00 | i32.const 0
+ 000056: fc 0c 00 00 | table.init 0 0
+ 00005a: fc 0d 00 | elem.drop 0
+ 00005d: 41 00 | i32.const 0
+ 00005f: 41 00 | i32.const 0
+ 000061: 41 00 | i32.const 0
+ 000063: fc 0e 00 00 | table.copy 0 0
+ 000067: 0b | end
+;;; STDOUT ;;)
diff --git a/test/dump/load64.txt b/test/dump/load64.txt
new file mode 100644
index 00000000..508c1cb7
--- /dev/null
+++ b/test/dump/load64.txt
@@ -0,0 +1,217 @@
+;;; TOOL: run-objdump
+;;; ARGS0: -v
+(module
+ (memory 1 i64)
+ (func
+ i64.const 0
+ i32.load
+ drop
+ i64.const 0
+ i32.load8_s
+ drop
+ i64.const 0
+ i32.load16_s
+ drop
+ i64.const 0
+ i32.load8_u
+ drop
+ i64.const 0
+ i32.load16_u
+ drop
+ i64.const 0
+ i64.load
+ drop
+ i64.const 0
+ i64.load8_s
+ drop
+ i64.const 0
+ i64.load16_s
+ drop
+ i64.const 0
+ i64.load32_s
+ drop
+ i64.const 0
+ i64.load8_u
+ drop
+ i64.const 0
+ i64.load16_u
+ drop
+ i64.const 0
+ i64.load32_u
+ drop
+ i64.const 0
+ f32.load
+ drop
+ i64.const 0
+ f64.load
+ drop))
+(;; STDOUT ;;;
+0000000: 0061 736d ; WASM_BINARY_MAGIC
+0000004: 0100 0000 ; WASM_BINARY_VERSION
+; section "Type" (1)
+0000008: 01 ; section code
+0000009: 00 ; section size (guess)
+000000a: 01 ; num types
+; type 0
+000000b: 60 ; func
+000000c: 00 ; num params
+000000d: 00 ; num results
+0000009: 04 ; FIXUP section size
+; section "Function" (3)
+000000e: 03 ; section code
+000000f: 00 ; section size (guess)
+0000010: 01 ; num functions
+0000011: 00 ; function 0 signature index
+000000f: 02 ; FIXUP section size
+; section "Memory" (5)
+0000012: 05 ; section code
+0000013: 00 ; section size (guess)
+0000014: 01 ; num memories
+; memory 0
+0000015: 04 ; limits: flags
+0000016: 01 ; limits: initial
+0000013: 03 ; FIXUP section size
+; section "Code" (10)
+0000017: 0a ; section code
+0000018: 00 ; section size (guess)
+0000019: 01 ; num functions
+; function body 0
+000001a: 00 ; func body size (guess)
+000001b: 00 ; local decl count
+000001c: 42 ; i64.const
+000001d: 00 ; i64 literal
+000001e: 28 ; i32.load
+000001f: 02 ; alignment
+0000020: 00 ; load offset
+0000021: 1a ; drop
+0000022: 42 ; i64.const
+0000023: 00 ; i64 literal
+0000024: 2c ; i32.load8_s
+0000025: 00 ; alignment
+0000026: 00 ; load offset
+0000027: 1a ; drop
+0000028: 42 ; i64.const
+0000029: 00 ; i64 literal
+000002a: 2e ; i32.load16_s
+000002b: 01 ; alignment
+000002c: 00 ; load offset
+000002d: 1a ; drop
+000002e: 42 ; i64.const
+000002f: 00 ; i64 literal
+0000030: 2d ; i32.load8_u
+0000031: 00 ; alignment
+0000032: 00 ; load offset
+0000033: 1a ; drop
+0000034: 42 ; i64.const
+0000035: 00 ; i64 literal
+0000036: 2f ; i32.load16_u
+0000037: 01 ; alignment
+0000038: 00 ; load offset
+0000039: 1a ; drop
+000003a: 42 ; i64.const
+000003b: 00 ; i64 literal
+000003c: 29 ; i64.load
+000003d: 03 ; alignment
+000003e: 00 ; load offset
+000003f: 1a ; drop
+0000040: 42 ; i64.const
+0000041: 00 ; i64 literal
+0000042: 30 ; i64.load8_s
+0000043: 00 ; alignment
+0000044: 00 ; load offset
+0000045: 1a ; drop
+0000046: 42 ; i64.const
+0000047: 00 ; i64 literal
+0000048: 32 ; i64.load16_s
+0000049: 01 ; alignment
+000004a: 00 ; load offset
+000004b: 1a ; drop
+000004c: 42 ; i64.const
+000004d: 00 ; i64 literal
+000004e: 34 ; i64.load32_s
+000004f: 02 ; alignment
+0000050: 00 ; load offset
+0000051: 1a ; drop
+0000052: 42 ; i64.const
+0000053: 00 ; i64 literal
+0000054: 31 ; i64.load8_u
+0000055: 00 ; alignment
+0000056: 00 ; load offset
+0000057: 1a ; drop
+0000058: 42 ; i64.const
+0000059: 00 ; i64 literal
+000005a: 33 ; i64.load16_u
+000005b: 01 ; alignment
+000005c: 00 ; load offset
+000005d: 1a ; drop
+000005e: 42 ; i64.const
+000005f: 00 ; i64 literal
+0000060: 35 ; i64.load32_u
+0000061: 02 ; alignment
+0000062: 00 ; load offset
+0000063: 1a ; drop
+0000064: 42 ; i64.const
+0000065: 00 ; i64 literal
+0000066: 2a ; f32.load
+0000067: 02 ; alignment
+0000068: 00 ; load offset
+0000069: 1a ; drop
+000006a: 42 ; i64.const
+000006b: 00 ; i64 literal
+000006c: 2b ; f64.load
+000006d: 03 ; alignment
+000006e: 00 ; load offset
+000006f: 1a ; drop
+0000070: 0b ; end
+000001a: 56 ; FIXUP func body size
+0000018: 58 ; FIXUP section size
+
+load64.wasm: file format wasm 0x1
+
+Code Disassembly:
+
+00001b func[0]:
+ 00001c: 42 00 | i64.const 0
+ 00001e: 28 02 00 | i32.load 2 0
+ 000021: 1a | drop
+ 000022: 42 00 | i64.const 0
+ 000024: 2c 00 00 | i32.load8_s 0 0
+ 000027: 1a | drop
+ 000028: 42 00 | i64.const 0
+ 00002a: 2e 01 00 | i32.load16_s 1 0
+ 00002d: 1a | drop
+ 00002e: 42 00 | i64.const 0
+ 000030: 2d 00 00 | i32.load8_u 0 0
+ 000033: 1a | drop
+ 000034: 42 00 | i64.const 0
+ 000036: 2f 01 00 | i32.load16_u 1 0
+ 000039: 1a | drop
+ 00003a: 42 00 | i64.const 0
+ 00003c: 29 03 00 | i64.load 3 0
+ 00003f: 1a | drop
+ 000040: 42 00 | i64.const 0
+ 000042: 30 00 00 | i64.load8_s 0 0
+ 000045: 1a | drop
+ 000046: 42 00 | i64.const 0
+ 000048: 32 01 00 | i64.load16_s 1 0
+ 00004b: 1a | drop
+ 00004c: 42 00 | i64.const 0
+ 00004e: 34 02 00 | i64.load32_s 2 0
+ 000051: 1a | drop
+ 000052: 42 00 | i64.const 0
+ 000054: 31 00 00 | i64.load8_u 0 0
+ 000057: 1a | drop
+ 000058: 42 00 | i64.const 0
+ 00005a: 33 01 00 | i64.load16_u 1 0
+ 00005d: 1a | drop
+ 00005e: 42 00 | i64.const 0
+ 000060: 35 02 00 | i64.load32_u 2 0
+ 000063: 1a | drop
+ 000064: 42 00 | i64.const 0
+ 000066: 2a 02 00 | f32.load 2 0
+ 000069: 1a | drop
+ 00006a: 42 00 | i64.const 0
+ 00006c: 2b 03 00 | f64.load 3 0
+ 00006f: 1a | drop
+ 000070: 0b | end
+;;; STDOUT ;;)
diff --git a/test/dump/store64.txt b/test/dump/store64.txt
new file mode 100644
index 00000000..f48447a8
--- /dev/null
+++ b/test/dump/store64.txt
@@ -0,0 +1,166 @@
+;;; TOOL: run-objdump
+;;; ARGS0: -v
+(module
+ (memory 1 i64)
+ (func
+ i64.const 0
+ i32.const 0
+ i32.store8
+ i64.const 0
+ i32.const 0
+ i32.store16
+ i64.const 0
+ i32.const 0
+ i32.store
+ i64.const 0
+ i64.const 0
+ i64.store
+ i64.const 0
+ i64.const 0
+ i64.store8
+ i64.const 0
+ i64.const 0
+ i64.store16
+ i64.const 0
+ i64.const 0
+ i64.store32
+ i64.const 0
+ f32.const 0
+ f32.store
+ i64.const 0
+ f64.const 0
+ f64.store))
+(;; STDOUT ;;;
+0000000: 0061 736d ; WASM_BINARY_MAGIC
+0000004: 0100 0000 ; WASM_BINARY_VERSION
+; section "Type" (1)
+0000008: 01 ; section code
+0000009: 00 ; section size (guess)
+000000a: 01 ; num types
+; type 0
+000000b: 60 ; func
+000000c: 00 ; num params
+000000d: 00 ; num results
+0000009: 04 ; FIXUP section size
+; section "Function" (3)
+000000e: 03 ; section code
+000000f: 00 ; section size (guess)
+0000010: 01 ; num functions
+0000011: 00 ; function 0 signature index
+000000f: 02 ; FIXUP section size
+; section "Memory" (5)
+0000012: 05 ; section code
+0000013: 00 ; section size (guess)
+0000014: 01 ; num memories
+; memory 0
+0000015: 04 ; limits: flags
+0000016: 01 ; limits: initial
+0000013: 03 ; FIXUP section size
+; section "Code" (10)
+0000017: 0a ; section code
+0000018: 00 ; section size (guess)
+0000019: 01 ; num functions
+; function body 0
+000001a: 00 ; func body size (guess)
+000001b: 00 ; local decl count
+000001c: 42 ; i64.const
+000001d: 00 ; i64 literal
+000001e: 41 ; i32.const
+000001f: 00 ; i32 literal
+0000020: 3a ; i32.store8
+0000021: 00 ; alignment
+0000022: 00 ; store offset
+0000023: 42 ; i64.const
+0000024: 00 ; i64 literal
+0000025: 41 ; i32.const
+0000026: 00 ; i32 literal
+0000027: 3b ; i32.store16
+0000028: 01 ; alignment
+0000029: 00 ; store offset
+000002a: 42 ; i64.const
+000002b: 00 ; i64 literal
+000002c: 41 ; i32.const
+000002d: 00 ; i32 literal
+000002e: 36 ; i32.store
+000002f: 02 ; alignment
+0000030: 00 ; store offset
+0000031: 42 ; i64.const
+0000032: 00 ; i64 literal
+0000033: 42 ; i64.const
+0000034: 00 ; i64 literal
+0000035: 37 ; i64.store
+0000036: 03 ; alignment
+0000037: 00 ; store offset
+0000038: 42 ; i64.const
+0000039: 00 ; i64 literal
+000003a: 42 ; i64.const
+000003b: 00 ; i64 literal
+000003c: 3c ; i64.store8
+000003d: 00 ; alignment
+000003e: 00 ; store offset
+000003f: 42 ; i64.const
+0000040: 00 ; i64 literal
+0000041: 42 ; i64.const
+0000042: 00 ; i64 literal
+0000043: 3d ; i64.store16
+0000044: 01 ; alignment
+0000045: 00 ; store offset
+0000046: 42 ; i64.const
+0000047: 00 ; i64 literal
+0000048: 42 ; i64.const
+0000049: 00 ; i64 literal
+000004a: 3e ; i64.store32
+000004b: 02 ; alignment
+000004c: 00 ; store offset
+000004d: 42 ; i64.const
+000004e: 00 ; i64 literal
+000004f: 43 ; f32.const
+0000050: 0000 0000 ; f32 literal
+0000054: 38 ; f32.store
+0000055: 02 ; alignment
+0000056: 00 ; store offset
+0000057: 42 ; i64.const
+0000058: 00 ; i64 literal
+0000059: 44 ; f64.const
+000005a: 0000 0000 0000 0000 ; f64 literal
+0000062: 39 ; f64.store
+0000063: 03 ; alignment
+0000064: 00 ; store offset
+0000065: 0b ; end
+000001a: 4b ; FIXUP func body size
+0000018: 4d ; FIXUP section size
+
+store64.wasm: file format wasm 0x1
+
+Code Disassembly:
+
+00001b func[0]:
+ 00001c: 42 00 | i64.const 0
+ 00001e: 41 00 | i32.const 0
+ 000020: 3a 00 00 | i32.store8 0 0
+ 000023: 42 00 | i64.const 0
+ 000025: 41 00 | i32.const 0
+ 000027: 3b 01 00 | i32.store16 1 0
+ 00002a: 42 00 | i64.const 0
+ 00002c: 41 00 | i32.const 0
+ 00002e: 36 02 00 | i32.store 2 0
+ 000031: 42 00 | i64.const 0
+ 000033: 42 00 | i64.const 0
+ 000035: 37 03 00 | i64.store 3 0
+ 000038: 42 00 | i64.const 0
+ 00003a: 42 00 | i64.const 0
+ 00003c: 3c 00 00 | i64.store8 0 0
+ 00003f: 42 00 | i64.const 0
+ 000041: 42 00 | i64.const 0
+ 000043: 3d 01 00 | i64.store16 1 0
+ 000046: 42 00 | i64.const 0
+ 000048: 42 00 | i64.const 0
+ 00004a: 3e 02 00 | i64.store32 2 0
+ 00004d: 42 00 | i64.const 0
+ 00004f: 43 00 00 00 00 | f32.const 0x0p+0
+ 000054: 38 02 00 | f32.store 2 0
+ 000057: 42 00 | i64.const 0
+ 000059: 44 00 00 00 00 00 00 00 00 | f64.const 0x0p+0
+ 000062: 39 03 00 | f64.store 3 0
+ 000065: 0b | end
+;;; STDOUT ;;)
diff --git a/test/gen-spec-wast.py b/test/gen-spec-wast.py
index 728d2214..a36b8e7f 100755
--- a/test/gen-spec-wast.py
+++ b/test/gen-spec-wast.py
@@ -249,6 +249,7 @@ def main(args):
parser.add_argument('--enable-bulk-memory', action='store_true')
parser.add_argument('--enable-tail-call', action='store_true')
parser.add_argument('--enable-reference-types', action='store_true')
+ parser.add_argument('--enable-memory64', action='store_true')
options = parser.parse_args(args)
wast2json = Executable(
@@ -266,6 +267,7 @@ def main(args):
'--enable-bulk-memory': options.enable_bulk_memory,
'--enable-tail-call': options.enable_tail_call,
'--enable-reference-types': options.enable_reference_types,
+ '--enable-memory64': options.enable_memory64,
})
json_filename = options.file
diff --git a/test/help/spectest-interp.txt b/test/help/spectest-interp.txt
index 46f25687..13ba5720 100644
--- a/test/help/spectest-interp.txt
+++ b/test/help/spectest-interp.txt
@@ -25,6 +25,7 @@ options:
--enable-reference-types Enable Reference types (externref)
--enable-annotations Enable Custom annotation syntax
--enable-gc Enable Garbage collection
+ --enable-memory64 Enable 64-bit memory
--enable-all Enable all features
-V, --value-stack-size=SIZE Size in elements of the value stack
-C, --call-stack-size=SIZE Size in elements of the call stack
diff --git a/test/help/wasm-interp.txt b/test/help/wasm-interp.txt
index e3c18ac1..d2af964f 100644
--- a/test/help/wasm-interp.txt
+++ b/test/help/wasm-interp.txt
@@ -36,6 +36,7 @@ options:
--enable-reference-types Enable Reference types (externref)
--enable-annotations Enable Custom annotation syntax
--enable-gc Enable Garbage collection
+ --enable-memory64 Enable 64-bit memory
--enable-all Enable all features
-V, --value-stack-size=SIZE Size in elements of the value stack
-C, --call-stack-size=SIZE Size in elements of the call stack
diff --git a/test/help/wasm-opcodecnt.txt b/test/help/wasm-opcodecnt.txt
index 28eddf1f..e3fe3edd 100644
--- a/test/help/wasm-opcodecnt.txt
+++ b/test/help/wasm-opcodecnt.txt
@@ -26,6 +26,7 @@ options:
--enable-reference-types Enable Reference types (externref)
--enable-annotations Enable Custom annotation syntax
--enable-gc Enable Garbage collection
+ --enable-memory64 Enable 64-bit memory
--enable-all Enable all features
-o, --output=FILENAME Output file for the opcode counts, by default use stdout
-c, --cutoff=N Cutoff for reporting counts less than N
diff --git a/test/help/wasm-validate.txt b/test/help/wasm-validate.txt
index 57584aa1..b01f1101 100644
--- a/test/help/wasm-validate.txt
+++ b/test/help/wasm-validate.txt
@@ -25,6 +25,7 @@ options:
--enable-reference-types Enable Reference types (externref)
--enable-annotations Enable Custom annotation syntax
--enable-gc Enable Garbage collection
+ --enable-memory64 Enable 64-bit memory
--enable-all Enable all features
--no-debug-names Ignore debug names in the binary file
--ignore-custom-section-errors Ignore errors in custom sections
diff --git a/test/help/wasm2wat.txt b/test/help/wasm2wat.txt
index 5f20154f..a7b26d4a 100644
--- a/test/help/wasm2wat.txt
+++ b/test/help/wasm2wat.txt
@@ -31,6 +31,7 @@ options:
--enable-reference-types Enable Reference types (externref)
--enable-annotations Enable Custom annotation syntax
--enable-gc Enable Garbage collection
+ --enable-memory64 Enable 64-bit memory
--enable-all Enable all features
--inline-exports Write all exports inline
--inline-imports Write all imports inline
diff --git a/test/help/wast2json.txt b/test/help/wast2json.txt
index 24f456be..a838d2d2 100644
--- a/test/help/wast2json.txt
+++ b/test/help/wast2json.txt
@@ -28,6 +28,7 @@ options:
--enable-reference-types Enable Reference types (externref)
--enable-annotations Enable Custom annotation syntax
--enable-gc Enable Garbage collection
+ --enable-memory64 Enable 64-bit memory
--enable-all Enable all features
-o, --output=FILE output JSON file
-r, --relocatable Create a relocatable wasm binary (suitable for linking with e.g. lld)
diff --git a/test/help/wat-desugar.txt b/test/help/wat-desugar.txt
index 65abc0d9..10076f78 100644
--- a/test/help/wat-desugar.txt
+++ b/test/help/wat-desugar.txt
@@ -35,6 +35,7 @@ options:
--enable-reference-types Enable Reference types (externref)
--enable-annotations Enable Custom annotation syntax
--enable-gc Enable Garbage collection
+ --enable-memory64 Enable 64-bit memory
--enable-all Enable all features
--generate-names Give auto-generated names to non-named functions, types, etc.
;;; STDOUT ;;)
diff --git a/test/help/wat2wasm.txt b/test/help/wat2wasm.txt
index 69114e6c..35f228f5 100644
--- a/test/help/wat2wasm.txt
+++ b/test/help/wat2wasm.txt
@@ -35,6 +35,7 @@ options:
--enable-reference-types Enable Reference types (externref)
--enable-annotations Enable Custom annotation syntax
--enable-gc Enable Garbage collection
+ --enable-memory64 Enable 64-bit memory
--enable-all Enable all features
-o, --output=FILE output wasm binary file
-r, --relocatable Create a relocatable wasm binary (suitable for linking with e.g. lld)
diff --git a/test/interp/load64.txt b/test/interp/load64.txt
new file mode 100644
index 00000000..232690ef
--- /dev/null
+++ b/test/interp/load64.txt
@@ -0,0 +1,73 @@
+;;; TOOL: run-interp
+(module
+ (memory 1 i64)
+ (data (i32.const 0) "\ff\ff\ff\ff")
+ (data (i32.const 4) "\00\00\ce\41")
+ (data (i32.const 8) "\00\00\00\00\00\ff\8f\40")
+ (data (i32.const 16) "\ff\ff\ff\ff\ff\ff\ff\ff")
+
+ (func (export "i32_load8_s") (result i32)
+ i64.const 0
+ i32.load8_s)
+ (func (export "i32_load16_s") (result i32)
+ i64.const 0
+ i32.load16_s)
+ (func (export "i32_load") (result i32)
+ i64.const 0
+ i32.load)
+
+ (func (export "i32_load8_u") (result i32)
+ i64.const 0
+ i32.load8_u)
+ (func (export "i32_load16_u") (result i32)
+ i64.const 0
+ i32.load16_u)
+
+ (func (export "i64_load8_s") (result i64)
+ i64.const 0
+ i64.load8_s)
+ (func (export "i64_load16_s") (result i64)
+ i64.const 0
+ i64.load16_s)
+ (func (export "i64_load32_s") (result i64)
+ i64.const 0
+ i64.load32_s)
+
+ (func (export "i64_load") (result i64)
+ i64.const 16
+ i64.load)
+
+ (func (export "i64_load8_u") (result i64)
+ i64.const 0
+ i64.load8_u)
+ (func (export "i64_load16_u") (result i64)
+ i64.const 0
+ i64.load16_u)
+ (func (export "i64_load32_u") (result i64)
+ i64.const 0
+ i64.load32_u)
+
+ (func (export "f32_load") (result f32)
+ i64.const 4
+ f32.load)
+
+ (func (export "f64_load") (result f64)
+ i64.const 8
+ f64.load)
+)
+(;; STDOUT ;;;
+i32_load8_s() => i32:4294967295
+i32_load16_s() => i32:4294967295
+i32_load() => i32:4294967295
+i32_load8_u() => i32:255
+i32_load16_u() => i32:65535
+i64_load8_s() => i64:18446744073709551615
+i64_load16_s() => i64:18446744073709551615
+i64_load32_s() => i64:18446744073709551615
+i64_load() => i64:18446744073709551615
+i64_load8_u() => i64:255
+i64_load16_u() => i64:65535
+i64_load32_u() => i64:4294967295
+f32_load() => f32:25.750000
+f64_load() => f64:1023.875000
+;;; STDOUT ;;)
diff --git a/test/interp/store64.txt b/test/interp/store64.txt
new file mode 100644
index 00000000..b1df7c08
--- /dev/null
+++ b/test/interp/store64.txt
@@ -0,0 +1,102 @@
+;;; TOOL: run-interp
+(module
+ (memory 1 i64)
+
+ (func (export "i32_store8") (result i32)
+ i64.const 0
+ i32.const 0xfb
+ i32.store8
+ i64.const 1
+ i32.const 0xfc
+ i32.store8
+ i64.const 2
+ i32.const 0xfd
+ i32.store8
+ i64.const 3
+ i32.const 0xfe
+ i32.store8
+ i64.const 0
+ i32.load)
+
+ (func (export "i32_store16") (result i32)
+ i64.const 0
+ i32.const 0xcac9
+ i32.store16
+ i64.const 2
+ i32.const 0xcccb
+ i32.store16
+ i64.const 0
+ i32.load)
+
+ (func (export "i32_store") (result i32)
+ i64.const 0
+ i32.const -123456
+ i32.store
+ i64.const 0
+ i32.load)
+
+ (func (export "i64_store8") (result i32)
+ i64.const 0
+ i64.const 0xeeeeeeeeeeeeeefb
+ i64.store8
+ i64.const 1
+ i64.const 0xeeeeeeeeeeeeeefc
+ i64.store8
+ i64.const 2
+ i64.const 0xeeeeeeeeeeeeeefd
+ i64.store8
+ i64.const 3
+ i64.const 0xeeeeeeeeeeeeeefe
+ i64.store8
+ i64.const 0
+ i32.load)
+
+ (func (export "i64_store16") (result i32)
+ i64.const 0
+ i64.const 0xeeeeeeeeeeeecac9
+ i64.store16
+ i64.const 2
+ i64.const 0xeeeeeeeeeeeecccb
+ i64.store16
+ i64.const 0
+ i32.load)
+
+ (func (export "i64_store32") (result i32)
+ i64.const 0
+ i64.const -123456
+ i64.store32
+ i64.const 0
+ i32.load)
+
+ (func (export "i64_store") (result i64)
+ i64.const 0
+ i64.const 0xbaddc0de600dd00d
+ i64.store
+ i64.const 0
+ i64.load)
+
+ (func (export "f32_store") (result i32)
+ i64.const 0
+ f32.const 1.5
+ f32.store
+ i64.const 0
+ i32.load)
+
+ (func (export "f64_store") (result i32)
+ i64.const 0
+ f64.const -1000.75
+ f64.store
+ i64.const 4
+ i32.load)
+)
+(;; STDOUT ;;;
+i32_store8() => i32:4278058235
+i32_store16() => i32:3435907785
+i32_store() => i32:4294843840
+i64_store8() => i32:4278058235
+i64_store16() => i32:3435907785
+i64_store32() => i32:4294843840
+i64_store() => i64:13465130522234441741
+f32_store() => i32:1069547520
+f64_store() => i32:3230615040
+;;; STDOUT ;;)
diff --git a/test/parse/expr/atomic64.txt b/test/parse/expr/atomic64.txt
new file mode 100644
index 00000000..356bf2fa
--- /dev/null
+++ b/test/parse/expr/atomic64.txt
@@ -0,0 +1,82 @@
+;;; TOOL: wat2wasm
+;;; ARGS: --enable-threads
+(module
+ (memory 1 1 shared i64)
+ (func
+ i64.const 0 i32.const 0 atomic.notify drop
+ i64.const 0 i32.const 0 i64.const 0 i32.atomic.wait drop
+ i64.const 0 i64.const 0 i64.const 0 i64.atomic.wait drop
+
+ i64.const 0 i32.atomic.load drop
+ i64.const 0 i64.atomic.load drop
+ i64.const 0 i32.atomic.load8_u drop
+ i64.const 0 i32.atomic.load16_u drop
+ i64.const 0 i64.atomic.load8_u drop
+ i64.const 0 i64.atomic.load16_u drop
+ i64.const 0 i64.atomic.load32_u drop
+
+ i64.const 0 i32.const 0 i32.atomic.store
+ i64.const 0 i64.const 0 i64.atomic.store
+ i64.const 0 i32.const 0 i32.atomic.store8
+ i64.const 0 i32.const 0 i32.atomic.store16
+ i64.const 0 i64.const 0 i64.atomic.store8
+ i64.const 0 i64.const 0 i64.atomic.store16
+ i64.const 0 i64.const 0 i64.atomic.store32
+
+ i64.const 0 i32.const 0 i32.atomic.rmw.add drop
+ i64.const 0 i64.const 0 i64.atomic.rmw.add drop
+ i64.const 0 i32.const 0 i32.atomic.rmw8.add_u drop
+ i64.const 0 i32.const 0 i32.atomic.rmw16.add_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw8.add_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw16.add_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw32.add_u drop
+
+ i64.const 0 i32.const 0 i32.atomic.rmw.sub drop
+ i64.const 0 i64.const 0 i64.atomic.rmw.sub drop
+ i64.const 0 i32.const 0 i32.atomic.rmw8.sub_u drop
+ i64.const 0 i32.const 0 i32.atomic.rmw16.sub_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw8.sub_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw16.sub_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw32.sub_u drop
+
+ i64.const 0 i32.const 0 i32.atomic.rmw.and drop
+ i64.const 0 i64.const 0 i64.atomic.rmw.and drop
+ i64.const 0 i32.const 0 i32.atomic.rmw8.and_u drop
+ i64.const 0 i32.const 0 i32.atomic.rmw16.and_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw8.and_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw16.and_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw32.and_u drop
+
+ i64.const 0 i32.const 0 i32.atomic.rmw.or drop
+ i64.const 0 i64.const 0 i64.atomic.rmw.or drop
+ i64.const 0 i32.const 0 i32.atomic.rmw8.or_u drop
+ i64.const 0 i32.const 0 i32.atomic.rmw16.or_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw8.or_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw16.or_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw32.or_u drop
+
+ i64.const 0 i32.const 0 i32.atomic.rmw.xor drop
+ i64.const 0 i64.const 0 i64.atomic.rmw.xor drop
+ i64.const 0 i32.const 0 i32.atomic.rmw8.xor_u drop
+ i64.const 0 i32.const 0 i32.atomic.rmw16.xor_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw8.xor_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw16.xor_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw32.xor_u drop
+
+ i64.const 0 i32.const 0 i32.atomic.rmw.xchg drop
+ i64.const 0 i64.const 0 i64.atomic.rmw.xchg drop
+ i64.const 0 i32.const 0 i32.atomic.rmw8.xchg_u drop
+ i64.const 0 i32.const 0 i32.atomic.rmw16.xchg_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw8.xchg_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw16.xchg_u drop
+ i64.const 0 i64.const 0 i64.atomic.rmw32.xchg_u drop
+
+ i64.const 0 i32.const 0 i32.const 0 i32.atomic.rmw.cmpxchg drop
+ i64.const 0 i64.const 0 i64.const 0 i64.atomic.rmw.cmpxchg drop
+ i64.const 0 i32.const 0 i32.const 0 i32.atomic.rmw8.cmpxchg_u drop
+ i64.const 0 i32.const 0 i32.const 0 i32.atomic.rmw16.cmpxchg_u drop
+ i64.const 0 i64.const 0 i64.const 0 i64.atomic.rmw8.cmpxchg_u drop
+ i64.const 0 i64.const 0 i64.const 0 i64.atomic.rmw16.cmpxchg_u drop
+ i64.const 0 i64.const 0 i64.const 0 i64.atomic.rmw32.cmpxchg_u drop
+
+))
diff --git a/test/parse/expr/bulk-memory-named64.txt b/test/parse/expr/bulk-memory-named64.txt
new file mode 100644
index 00000000..acd21119
--- /dev/null
+++ b/test/parse/expr/bulk-memory-named64.txt
@@ -0,0 +1,19 @@
+;;; TOOL: wat2wasm
+;;; ARGS: --enable-bulk-memory
+
+(module
+ (memory 1 i64)
+ (data $data "a")
+ (func
+ i64.const 0 i32.const 0 i32.const 0 memory.init $data
+ data.drop $data
+ )
+
+ (table 1 anyfunc)
+ (elem $elem funcref (ref.func 0) (ref.null func))
+ (elem $elem2 func 0)
+ (func
+ i32.const 0 i32.const 0 i32.const 0 table.init $elem
+ elem.drop $elem
+ )
+)
diff --git a/test/parse/expr/grow-memory64.txt b/test/parse/expr/grow-memory64.txt
new file mode 100644
index 00000000..86157173
--- /dev/null
+++ b/test/parse/expr/grow-memory64.txt
@@ -0,0 +1,8 @@
+;;; TOOL: wat2wasm
+;;; ARGS: --enable-memory64
+(module
+ (memory 1 i64)
+ (func
+ i64.const 100
+ grow_memory
+ drop))
diff --git a/test/parse/expr/load64.txt b/test/parse/expr/load64.txt
new file mode 100644
index 00000000..c5e138fa
--- /dev/null
+++ b/test/parse/expr/load64.txt
@@ -0,0 +1,46 @@
+;;; TOOL: wat2wasm
+(module
+ (memory 1 i64)
+ (func
+ i64.const 0
+ i32.load
+ drop
+ i64.const 0
+ i32.load8_s
+ drop
+ i64.const 0
+ i32.load16_s
+ drop
+ i64.const 0
+ i32.load8_u
+ drop
+ i64.const 0
+ i32.load16_u
+ drop
+ i64.const 0
+ i64.load
+ drop
+ i64.const 0
+ i64.load8_s
+ drop
+ i64.const 0
+ i64.load16_s
+ drop
+ i64.const 0
+ i64.load32_s
+ drop
+ i64.const 0
+ i64.load8_u
+ drop
+ i64.const 0
+ i64.load16_u
+ drop
+ i64.const 0
+ i64.load32_u
+ drop
+ i64.const 0
+ f32.load
+ drop
+ i64.const 0
+ f64.load
+ drop))
diff --git a/test/parse/expr/memory-copy64.txt b/test/parse/expr/memory-copy64.txt
new file mode 100644
index 00000000..aa942e99
--- /dev/null
+++ b/test/parse/expr/memory-copy64.txt
@@ -0,0 +1,10 @@
+;;; TOOL: wat2wasm
+;;; ARGS: --enable-bulk-memory --enable-memory64
+(module
+ (memory 0 i64)
+
+ (func
+ i64.const 0
+ i64.const 0
+ i64.const 0
+ memory.copy))
diff --git a/test/parse/expr/memory-fill64.txt b/test/parse/expr/memory-fill64.txt
new file mode 100644
index 00000000..fb7eaf37
--- /dev/null
+++ b/test/parse/expr/memory-fill64.txt
@@ -0,0 +1,10 @@
+;;; TOOL: wat2wasm
+;;; ARGS: --enable-bulk-memory --enable-memory64
+(module
+ (memory 0 i64)
+
+ (func
+ i64.const 0
+ i32.const 0
+ i64.const 0
+ memory.fill))
diff --git a/test/parse/expr/memory-init64.txt b/test/parse/expr/memory-init64.txt
new file mode 100644
index 00000000..93fe469e
--- /dev/null
+++ b/test/parse/expr/memory-init64.txt
@@ -0,0 +1,12 @@
+;;; TOOL: wat2wasm
+;;; ARGS: --enable-bulk-memory --enable-memory64
+(module
+ (memory 0 i64)
+
+ (func
+ i64.const 0
+ i32.const 0
+ i32.const 0
+ memory.init 0)
+
+ (data "hi"))
diff --git a/test/parse/expr/store64.txt b/test/parse/expr/store64.txt
new file mode 100644
index 00000000..5f81e2e6
--- /dev/null
+++ b/test/parse/expr/store64.txt
@@ -0,0 +1,31 @@
+;;; TOOL: wat2wasm
+(module
+ (memory 1 i64)
+ (func
+ i64.const 0
+ i32.const 0
+ i32.store8
+ i64.const 0
+ i32.const 0
+ i32.store16
+ i64.const 0
+ i32.const 0
+ i32.store
+ i64.const 0
+ i64.const 0
+ i64.store
+ i64.const 0
+ i64.const 0
+ i64.store8
+ i64.const 0
+ i64.const 0
+ i64.store16
+ i64.const 0
+ i64.const 0
+ i64.store32
+ i64.const 0
+ f32.const 0
+ f32.store
+ i64.const 0
+ f64.const 0
+ f64.store))
diff --git a/test/roundtrip/bulk-memory64.txt b/test/roundtrip/bulk-memory64.txt
new file mode 100644
index 00000000..c6513a34
--- /dev/null
+++ b/test/roundtrip/bulk-memory64.txt
@@ -0,0 +1,78 @@
+;;; TOOL: run-roundtrip
+;;; ARGS: --stdout --enable-bulk-memory
+(module
+ (memory 0 i64)
+ (table 0 anyfunc)
+
+ (func
+ i64.const 0
+ i32.const 0
+ i32.const 0
+ memory.init 0
+
+ data.drop 0
+
+ i64.const 0
+ i64.const 0
+ i64.const 0
+ memory.copy
+
+ i64.const 0
+ i32.const 0
+ i64.const 0
+ memory.fill
+
+ i32.const 0
+ i32.const 0
+ i32.const 0
+ table.init 0
+
+ elem.drop 0
+
+ i32.const 0
+ i32.const 0
+ i32.const 0
+ table.copy
+
+ )
+
+ (func)
+
+ (data "hi")
+ (elem funcref (ref.func 0) (ref.null func))
+ (elem func 1)
+
+)
+(;; STDOUT ;;;
+(module
+ (type (;0;) (func))
+ (func (;0;) (type 0)
+ i64.const 0
+ i32.const 0
+ i32.const 0
+ memory.init 0
+ data.drop 0
+ i64.const 0
+ i64.const 0
+ i64.const 0
+ memory.copy
+ i64.const 0
+ i32.const 0
+ i64.const 0
+ memory.fill
+ i32.const 0
+ i32.const 0
+ i32.const 0
+ table.init 0
+ elem.drop 0
+ i32.const 0
+ i32.const 0
+ i32.const 0
+ table.copy)
+ (func (;1;) (type 0))
+ (table (;0;) 0 funcref)
+ (memory (;0;) 0 i64)
+ (elem (;0;) funcref (ref.func 0) (ref.null func))
+ (elem (;1;) func 1)
+ (data (;0;) "hi"))
+;;; STDOUT ;;)
diff --git a/test/roundtrip/fold-load-store64.txt b/test/roundtrip/fold-load-store64.txt
new file mode 100644
index 00000000..67466b0f
--- /dev/null
+++ b/test/roundtrip/fold-load-store64.txt
@@ -0,0 +1,59 @@
+;;; TOOL: run-roundtrip
+;;; ARGS: --stdout --fold-exprs --enable-memory64
+(module
+ (memory 1 i64)
+ (func $fold-load
+ i64.const 1
+ i32.load
+ drop
+ i64.const 2
+ i32.load
+ drop)
+
+ (func $fold-store
+ i64.const 1
+ i64.load
+ f32.const 2
+ f32.store)
+
+ (func $fold-current-memory (result i32)
+ current_memory
+ i64.const 1
+ i64.add
+ drop
+ i32.const 2)
+
+ (func $fold-grow-memory (result i32)
+ i64.const 1
+ i64.const 2
+ grow_memory
+ i64.lt_s))
+(;; STDOUT ;;;
+(module
+ (type (;0;) (func))
+ (type (;1;) (func (result i32)))
+ (func (;0;) (type 0)
+ (drop
+ (i32.load
+ (i64.const 1)))
+ (drop
+ (i32.load
+ (i64.const 2))))
+ (func (;1;) (type 0)
+ (f32.store
+ (i64.load
+ (i64.const 1))
+ (f32.const 0x1p+1 (;=2;))))
+ (func (;2;) (type 1) (result i32)
+ (drop
+ (i64.add
+ (memory.size)
+ (i64.const 1)))
+ (i32.const 2))
+ (func (;3;) (type 1) (result i32)
+ (i64.lt_s
+ (i64.const 1)
+ (memory.grow
+ (i64.const 2))))
+ (memory (;0;) 1 i64))
+;;; STDOUT ;;)
diff --git a/test/roundtrip/memory-index64.txt b/test/roundtrip/memory-index64.txt
new file mode 100644
index 00000000..30f81dec
--- /dev/null
+++ b/test/roundtrip/memory-index64.txt
@@ -0,0 +1,8 @@
+;;; TOOL: run-roundtrip
+;;; ARGS: --stdout
+(module
+ (import "a" "b" (memory 1 i64)))
+(;; STDOUT ;;;
+(module
+ (import "a" "b" (memory (;0;) 1 i64)))
+;;; STDOUT ;;)
diff --git a/test/run-roundtrip.py b/test/run-roundtrip.py
index 5f28fa9c..46e96430 100755
--- a/test/run-roundtrip.py
+++ b/test/run-roundtrip.py
@@ -123,6 +123,7 @@ def main(args):
parser.add_argument('--enable-bulk-memory', action='store_true')
parser.add_argument('--enable-tail-call', action='store_true')
parser.add_argument('--enable-reference-types', action='store_true')
+ parser.add_argument('--enable-memory64', action='store_true')
parser.add_argument('--inline-exports', action='store_true')
parser.add_argument('--inline-imports', action='store_true')
parser.add_argument('file', help='test file.')
@@ -143,6 +144,7 @@ def main(args):
'--enable-bulk-memory': options.enable_bulk_memory,
'--enable-tail-call': options.enable_tail_call,
'--enable-reference-types': options.enable_reference_types,
+ '--enable-memory64': options.enable_memory64,
'--no-check': options.no_check,
})
@@ -161,6 +163,7 @@ def main(args):
'--enable-tail-call': options.enable_tail_call,
'--enable-reference-types': options.enable_reference_types,
'--enable-threads': options.enable_threads,
+ '--enable-memory64': options.enable_memory64,
'--inline-exports': options.inline_exports,
'--inline-imports': options.inline_imports,
'--no-debug-names': not options.debug_names,
diff --git a/test/spec/memory.txt b/test/spec/memory.txt
index 87446f72..5fdf5eed 100644
--- a/test/spec/memory.txt
+++ b/test/spec/memory.txt
@@ -17,17 +17,13 @@ out/test/spec/memory.wast:22: assert_invalid passed:
0000000: error: memory variable out of range: 0 (max 0)
000000c: error: BeginDataSegment callback failed
out/test/spec/memory.wast:25: assert_invalid passed:
- error: memory variable out of range: 0 (max 0)
- 000001c: error: OnLoadExpr callback failed
+ 000001b: error: load/store memory 0 out of range 0
out/test/spec/memory.wast:29: assert_invalid passed:
- error: memory variable out of range: 0 (max 0)
- 0000021: error: OnStoreExpr callback failed
+ 0000020: error: load/store memory 0 out of range 0
out/test/spec/memory.wast:33: assert_invalid passed:
- error: memory variable out of range: 0 (max 0)
- 000001c: error: OnLoadExpr callback failed
+ 000001b: error: load/store memory 0 out of range 0
out/test/spec/memory.wast:37: assert_invalid passed:
- error: memory variable out of range: 0 (max 0)
- 000001e: error: OnStoreExpr callback failed
+ 000001d: error: load/store memory 0 out of range 0
out/test/spec/memory.wast:41: assert_invalid passed:
error: memory variable out of range: 0 (max 0)
0000019: error: OnMemorySizeExpr callback failed