summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorYuhan Deng <31569419+yhdengh@users.noreply.github.com>2021-11-30 14:04:40 -0800
committerGitHub <noreply@github.com>2021-11-30 22:04:40 +0000
commitcf1e138ba9cde79d51f56d873e10b7ac9e4481b1 (patch)
tree22451a2d589797e4fd3c653e90ab7859234b38d0 /src
parentf65fadeedff3458e1dd9c157553cd0ed891683dd (diff)
downloadwabt-cf1e138ba9cde79d51f56d873e10b7ac9e4481b1.tar.gz
wabt-cf1e138ba9cde79d51f56d873e10b7ac9e4481b1.tar.bz2
wabt-cf1e138ba9cde79d51f56d873e10b7ac9e4481b1.zip
Add multi-memory feature support (#1751)
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-ir.cc41
-rw-r--r--src/binary-reader-logging.cc23
-rw-r--r--src/binary-reader-logging.h12
-rw-r--r--src/binary-reader-nop.h16
-rw-r--r--src/binary-reader.cc124
-rw-r--r--src/binary-reader.h12
-rw-r--r--src/binary-writer.cc74
-rw-r--r--src/c-writer.cc29
-rw-r--r--src/feature.def1
-rw-r--r--src/interp/binary-reader-interp.cc56
-rw-r--r--src/ir.h68
-rw-r--r--src/resolve-names.cc38
-rw-r--r--src/shared-validator.cc31
-rw-r--r--src/shared-validator.h14
-rw-r--r--src/validator.cc15
-rw-r--r--src/wast-parser.cc98
-rw-r--r--src/wast-parser.h9
-rw-r--r--src/wat-writer.cc67
18 files changed, 557 insertions, 171 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index f454174b..27e97c85 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -165,18 +165,19 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnI64ConstExpr(uint64_t value) override;
Result OnIfExpr(Type sig_type) override;
Result OnLoadExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) override;
Result OnLocalGetExpr(Index local_index) override;
Result OnLocalSetExpr(Index local_index) override;
Result OnLocalTeeExpr(Index local_index) override;
Result OnLoopExpr(Type sig_type) override;
- Result OnMemoryCopyExpr() override;
+ Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override;
Result OnDataDropExpr(Index segment_index) override;
- Result OnMemoryFillExpr() override;
- Result OnMemoryGrowExpr() override;
- Result OnMemoryInitExpr(Index segment_index) override;
- Result OnMemorySizeExpr() override;
+ Result OnMemoryFillExpr(Index memidx) override;
+ Result OnMemoryGrowExpr(Index memidx) override;
+ Result OnMemoryInitExpr(Index segment_index, Index memidx) override;
+ Result OnMemorySizeExpr(Index memidx) override;
Result OnTableCopyExpr(Index dst_index, Index src_index) override;
Result OnElemDropExpr(Index segment_index) override;
Result OnTableInitExpr(Index segment_index, Index table_index) override;
@@ -193,6 +194,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnReturnExpr() override;
Result OnSelectExpr(Index result_count, Type* result_types) override;
Result OnStoreExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) override;
Result OnThrowExpr(Index tag_index) override;
@@ -873,9 +875,11 @@ Result BinaryReaderIR::OnIfExpr(Type sig_type) {
}
Result BinaryReaderIR::OnLoadExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) {
- return AppendExpr(MakeUnique<LoadExpr>(opcode, 1 << alignment_log2, offset));
+ return AppendExpr(
+ MakeUnique<LoadExpr>(opcode, Var(memidx), 1 << alignment_log2, offset));
}
Result BinaryReaderIR::OnLoopExpr(Type sig_type) {
@@ -887,28 +891,29 @@ Result BinaryReaderIR::OnLoopExpr(Type sig_type) {
return Result::Ok;
}
-Result BinaryReaderIR::OnMemoryCopyExpr() {
- return AppendExpr(MakeUnique<MemoryCopyExpr>());
+Result BinaryReaderIR::OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) {
+ return AppendExpr(
+ MakeUnique<MemoryCopyExpr>(Var(srcmemidx), Var(destmemidx)));
}
Result BinaryReaderIR::OnDataDropExpr(Index segment) {
return AppendExpr(MakeUnique<DataDropExpr>(Var(segment)));
}
-Result BinaryReaderIR::OnMemoryFillExpr() {
- return AppendExpr(MakeUnique<MemoryFillExpr>());
+Result BinaryReaderIR::OnMemoryFillExpr(Index memidx) {
+ return AppendExpr(MakeUnique<MemoryFillExpr>(Var(memidx)));
}
-Result BinaryReaderIR::OnMemoryGrowExpr() {
- return AppendExpr(MakeUnique<MemoryGrowExpr>());
+Result BinaryReaderIR::OnMemoryGrowExpr(Index memidx) {
+ return AppendExpr(MakeUnique<MemoryGrowExpr>(Var(memidx)));
}
-Result BinaryReaderIR::OnMemoryInitExpr(Index segment) {
- return AppendExpr(MakeUnique<MemoryInitExpr>(Var(segment)));
+Result BinaryReaderIR::OnMemoryInitExpr(Index segment, Index memidx) {
+ return AppendExpr(MakeUnique<MemoryInitExpr>(Var(segment), Var(memidx)));
}
-Result BinaryReaderIR::OnMemorySizeExpr() {
- return AppendExpr(MakeUnique<MemorySizeExpr>());
+Result BinaryReaderIR::OnMemorySizeExpr(Index memidx) {
+ return AppendExpr(MakeUnique<MemorySizeExpr>(Var(memidx)));
}
Result BinaryReaderIR::OnTableCopyExpr(Index dst_index, Index src_index) {
@@ -983,9 +988,11 @@ Result BinaryReaderIR::OnLocalSetExpr(Index local_index) {
}
Result BinaryReaderIR::OnStoreExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) {
- return AppendExpr(MakeUnique<StoreExpr>(opcode, 1 << alignment_log2, offset));
+ return AppendExpr(
+ MakeUnique<StoreExpr>(opcode, Var(memidx), 1 << alignment_log2, offset));
}
Result BinaryReaderIR::OnThrowExpr(Index tag_index) {
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc
index 9fa906ba..6e0779a5 100644
--- a/src/binary-reader-logging.cc
+++ b/src/binary-reader-logging.cc
@@ -748,6 +748,15 @@ Result BinaryReaderLogging::OnComdatEntry(ComdatType kind, Index index) {
return reader_->name(opcode, alignment_log2, offset); \
}
+#define DEFINE_MEMORY_LOAD_STORE_OPCODE(name) \
+ Result BinaryReaderLogging::name(Opcode opcode, Index memidx, \
+ Address alignment_log2, Address offset) { \
+ LOGF(#name "(opcode: \"%s\" (%u), memidx: %" PRIindex \
+ ", align log2: %" PRIaddress ", offset: %" PRIaddress ")\n", \
+ opcode.GetName(), opcode.GetCode(), memidx, alignment_log2, offset); \
+ return reader_->name(opcode, memidx, alignment_log2, offset); \
+ }
+
#define DEFINE_SIMD_LOAD_STORE_LANE_OPCODE(name) \
Result BinaryReaderLogging::name(Opcode opcode, Address alignment_log2, \
Address offset, uint64_t value) { \
@@ -828,16 +837,16 @@ DEFINE0(OnElseExpr)
DEFINE0(OnEndExpr)
DEFINE_INDEX_DESC(OnGlobalGetExpr, "index")
DEFINE_INDEX_DESC(OnGlobalSetExpr, "index")
-DEFINE_LOAD_STORE_OPCODE(OnLoadExpr);
+DEFINE_MEMORY_LOAD_STORE_OPCODE(OnLoadExpr);
DEFINE_INDEX_DESC(OnLocalGetExpr, "index")
DEFINE_INDEX_DESC(OnLocalSetExpr, "index")
DEFINE_INDEX_DESC(OnLocalTeeExpr, "index")
-DEFINE0(OnMemoryCopyExpr)
+DEFINE_INDEX_INDEX(OnMemoryCopyExpr, "src_memory_index", "dest_memory_index")
DEFINE_INDEX(OnDataDropExpr)
-DEFINE0(OnMemoryFillExpr)
-DEFINE0(OnMemoryGrowExpr)
-DEFINE_INDEX(OnMemoryInitExpr)
-DEFINE0(OnMemorySizeExpr)
+DEFINE_INDEX(OnMemoryFillExpr)
+DEFINE_INDEX(OnMemoryGrowExpr)
+DEFINE_INDEX_INDEX(OnMemoryInitExpr, "segment_index", "memory_index")
+DEFINE_INDEX(OnMemorySizeExpr)
DEFINE_INDEX_INDEX(OnTableCopyExpr, "dst_index", "src_index")
DEFINE_INDEX(OnElemDropExpr)
DEFINE_INDEX_INDEX(OnTableInitExpr, "segment_index", "table_index")
@@ -857,7 +866,7 @@ DEFINE_INDEX_INDEX(OnReturnCallIndirectExpr, "sig_index", "table_index")
DEFINE0(OnReturnExpr)
DEFINE_LOAD_STORE_OPCODE(OnLoadSplatExpr);
DEFINE_LOAD_STORE_OPCODE(OnLoadZeroExpr);
-DEFINE_LOAD_STORE_OPCODE(OnStoreExpr);
+DEFINE_MEMORY_LOAD_STORE_OPCODE(OnStoreExpr);
DEFINE_INDEX_DESC(OnThrowExpr, "tag_index")
DEFINE0(OnUnreachableExpr)
DEFINE_OPCODE(OnUnaryExpr)
diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h
index 41ecf07d..d1531b35 100644
--- a/src/binary-reader-logging.h
+++ b/src/binary-reader-logging.h
@@ -185,18 +185,19 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnI64ConstExpr(uint64_t value) override;
Result OnIfExpr(Type sig_type) override;
Result OnLoadExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) override;
Result OnLocalGetExpr(Index local_index) override;
Result OnLocalSetExpr(Index local_index) override;
Result OnLocalTeeExpr(Index local_index) override;
Result OnLoopExpr(Type sig_type) override;
- Result OnMemoryCopyExpr() override;
+ Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override;
Result OnDataDropExpr(Index segment_index) override;
- Result OnMemoryFillExpr() override;
- Result OnMemoryGrowExpr() override;
- Result OnMemoryInitExpr(Index segment_index) override;
- Result OnMemorySizeExpr() override;
+ Result OnMemoryFillExpr(Index memidx) override;
+ Result OnMemoryGrowExpr(Index memidx) override;
+ Result OnMemoryInitExpr(Index segment_index, Index memidx) override;
+ Result OnMemorySizeExpr(Index memidx) override;
Result OnTableCopyExpr(Index dst_index, Index src_index) override;
Result OnElemDropExpr(Index segment_index) override;
Result OnTableInitExpr(Index segment_index, Index table_index) override;
@@ -215,6 +216,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result OnReturnExpr() override;
Result OnSelectExpr(Index result_count, Type* result_types) override;
Result OnStoreExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) override;
Result OnThrowExpr(Index tag_index) override;
diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h
index 167ea8c7..256ac920 100644
--- a/src/binary-reader-nop.h
+++ b/src/binary-reader-nop.h
@@ -256,6 +256,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,
+ Index memidx,
Address alignment_log2,
Address offset) override {
return Result::Ok;
@@ -264,12 +265,16 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnLocalSetExpr(Index local_index) override { return Result::Ok; }
Result OnLocalTeeExpr(Index local_index) override { return Result::Ok; }
Result OnLoopExpr(Type sig_type) override { return Result::Ok; }
- Result OnMemoryCopyExpr() override { return Result::Ok; }
+ Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override {
+ return Result::Ok;
+ }
Result OnDataDropExpr(Index segment_index) override { return Result::Ok; }
- Result OnMemoryFillExpr() override { return Result::Ok; }
- Result OnMemoryGrowExpr() override { return Result::Ok; }
- Result OnMemoryInitExpr(Index segment_index) override { return Result::Ok; }
- Result OnMemorySizeExpr() override { return Result::Ok; }
+ Result OnMemoryFillExpr(Index memidx) override { return Result::Ok; }
+ Result OnMemoryGrowExpr(Index memidx) override { return Result::Ok; }
+ Result OnMemoryInitExpr(Index segment_index, Index memidx) override {
+ return Result::Ok;
+ }
+ Result OnMemorySizeExpr(Index memidx) override { return Result::Ok; }
Result OnTableCopyExpr(Index dst_index, Index src_index) override {
return Result::Ok;
}
@@ -294,6 +299,7 @@ class BinaryReaderNop : public BinaryReaderDelegate {
return Result::Ok;
}
Result OnStoreExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) override {
return Result::Ok;
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index 9c6aeffb..c146c7ec 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -110,6 +110,7 @@ class BinaryReader {
Result ReadIndex(Index* index, const char* desc) WABT_WARN_UNUSED;
Result ReadOffset(Offset* offset, const char* desc) WABT_WARN_UNUSED;
Result ReadAlignment(Address* align_log2, const char* desc) WABT_WARN_UNUSED;
+ Result ReadMemidx(Index* memidx, const char* desc) WABT_WARN_UNUSED;
Result ReadCount(Index* index, const char* desc) WABT_WARN_UNUSED;
Result ReadField(TypeMut* out_value) WABT_WARN_UNUSED;
@@ -398,7 +399,8 @@ Result BinaryReader::ReadOffset(Offset* offset, const char* desc) {
Result BinaryReader::ReadAlignment(Address* alignment_log2, const char* desc) {
uint32_t value;
CHECK_RESULT(ReadU32Leb128(&value, desc));
- if (value >= 32) {
+ if (value >= 128 ||
+ (value >= 32 && !options_.features.multi_memory_enabled())) {
PrintError("invalid %s: %u", desc, value);
return Result::Error;
}
@@ -406,6 +408,13 @@ Result BinaryReader::ReadAlignment(Address* alignment_log2, const char* desc) {
return Result::Ok;
}
+Result BinaryReader::ReadMemidx(Index* memidx, const char* desc) {
+ CHECK_RESULT(ReadIndex(memidx, desc));
+ ERROR_UNLESS(*memidx < memories.size(), "memory index %u out of range",
+ *memidx);
+ return Result::Ok;
+}
+
Result BinaryReader::ReadCount(Index* count, const char* desc) {
CHECK_RESULT(ReadIndex(count, desc));
@@ -953,8 +962,20 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
CHECK_RESULT(ReadAlignment(&alignment_log2, "load alignment"));
Address offset;
CHECK_RESULT(ReadAddress(&offset, 0, "load offset"));
- CALLBACK(OnLoadExpr, opcode, alignment_log2, offset);
- CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
+ Index memidx = 0;
+ if (alignment_log2 >> 6) {
+ ERROR_IF(!options_.features.multi_memory_enabled(),
+ "multi_memory not allowed");
+ CHECK_RESULT(ReadMemidx(&memidx, "store memidx"));
+ alignment_log2 = alignment_log2 & ((1 << 6) - 1);
+ }
+
+ CALLBACK(OnLoadExpr, opcode, memidx, alignment_log2, offset);
+ if (memidx) {
+ CALLBACK(OnOpcodeUint32Uint32Uint32, alignment_log2, offset, memidx);
+ } else {
+ CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
+ }
break;
}
@@ -972,27 +993,48 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
CHECK_RESULT(ReadAlignment(&alignment_log2, "store alignment"));
Address offset;
CHECK_RESULT(ReadAddress(&offset, 0, "store offset"));
+ Index memidx = 0;
+ if (alignment_log2 >> 6) {
+ ERROR_IF(!options_.features.multi_memory_enabled(),
+ "multi_memory not allowed");
+ CHECK_RESULT(ReadMemidx(&memidx, "store memidx"));
+ alignment_log2 = alignment_log2 & ((1 << 6) - 1);
+ }
- CALLBACK(OnStoreExpr, opcode, alignment_log2, offset);
- CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
+ CALLBACK(OnStoreExpr, opcode, memidx, alignment_log2, offset);
+ if (memidx) {
+ CALLBACK(OnOpcodeUint32Uint32Uint32, alignment_log2, offset, memidx);
+ } else {
+ CALLBACK(OnOpcodeUint32Uint32, alignment_log2, offset);
+ }
break;
}
case Opcode::MemorySize: {
- uint8_t reserved;
- CHECK_RESULT(ReadU8(&reserved, "memory.size reserved"));
- ERROR_UNLESS(reserved == 0, "memory.size reserved value must be 0");
- CALLBACK0(OnMemorySizeExpr);
- CALLBACK(OnOpcodeUint32, reserved);
+ Index memidx = 0;
+ if (!options_.features.multi_memory_enabled()) {
+ uint8_t reserved;
+ CHECK_RESULT(ReadU8(&reserved, "memory.size reserved"));
+ ERROR_UNLESS(reserved == 0, "memory.size reserved value must be 0");
+ } else {
+ CHECK_RESULT(ReadMemidx(&memidx, "memory.size memidx"));
+ }
+ CALLBACK(OnMemorySizeExpr, memidx);
+ CALLBACK(OnOpcodeUint32, memidx);
break;
}
case Opcode::MemoryGrow: {
- uint8_t reserved;
- CHECK_RESULT(ReadU8(&reserved, "memory.grow reserved"));
- ERROR_UNLESS(reserved == 0, "memory.grow reserved value must be 0");
- CALLBACK0(OnMemoryGrowExpr);
- CALLBACK(OnOpcodeUint32, reserved);
+ Index memidx = 0;
+ if (!options_.features.multi_memory_enabled()) {
+ uint8_t reserved;
+ CHECK_RESULT(ReadU8(&reserved, "memory.grow reserved"));
+ ERROR_UNLESS(reserved == 0, "memory.grow reserved value must be 0");
+ } else {
+ CHECK_RESULT(ReadMemidx(&memidx, "memory.grow memidx"));
+ }
+ CALLBACK(OnMemoryGrowExpr, memidx);
+ CALLBACK(OnOpcodeUint32, memidx);
break;
}
@@ -1640,11 +1682,16 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
ERROR_IF(data_count_ == kInvalidIndex,
"memory.init requires data count section");
CHECK_RESULT(ReadIndex(&segment, "elem segment index"));
- uint8_t reserved;
- CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
- ERROR_UNLESS(reserved == 0, "reserved value must be 0");
- CALLBACK(OnMemoryInitExpr, segment);
- CALLBACK(OnOpcodeUint32Uint32, segment, reserved);
+ Index memidx = 0;
+ if (!options_.features.multi_memory_enabled()) {
+ uint8_t reserved;
+ CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
+ ERROR_UNLESS(reserved == 0, "reserved value must be 0");
+ } else {
+ CHECK_RESULT(ReadMemidx(&memidx, "memory.init memidx"));
+ }
+ CALLBACK(OnMemoryInitExpr, segment, memidx);
+ CALLBACK(OnOpcodeUint32Uint32, segment, memidx);
break;
}
@@ -1665,21 +1712,34 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
}
case Opcode::MemoryFill: {
- uint8_t reserved;
- CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
- ERROR_UNLESS(reserved == 0, "reserved value must be 0");
- CALLBACK(OnMemoryFillExpr);
- CALLBACK(OnOpcodeUint32, reserved);
+ Index memidx = 0;
+ if (!options_.features.multi_memory_enabled()) {
+ uint8_t reserved;
+ CHECK_RESULT(ReadU8(&reserved, "memory.fill reserved"));
+ ERROR_UNLESS(reserved == 0, "memory.fill reserved value must be 0");
+ } else {
+ CHECK_RESULT(ReadMemidx(&memidx, "memory.fill memidx"));
+ }
+ CALLBACK(OnMemoryFillExpr, memidx);
+ CALLBACK(OnOpcodeUint32, memidx);
break;
}
+
case Opcode::MemoryCopy: {
- uint8_t reserved;
- CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
- ERROR_UNLESS(reserved == 0, "reserved value must be 0");
- CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
- ERROR_UNLESS(reserved == 0, "reserved value must be 0");
- CALLBACK(OnMemoryCopyExpr);
- CALLBACK(OnOpcodeUint32Uint32, reserved, reserved);
+ Index srcmemidx = 0;
+ Index destmemidx = 0;
+ if (!options_.features.multi_memory_enabled()) {
+ uint8_t reserved;
+ CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
+ ERROR_UNLESS(reserved == 0, "reserved value must be 0");
+ CHECK_RESULT(ReadU8(&reserved, "reserved memory index"));
+ ERROR_UNLESS(reserved == 0, "reserved value must be 0");
+ } else {
+ CHECK_RESULT(ReadMemidx(&srcmemidx, "memory.copy srcmemidx"));
+ CHECK_RESULT(ReadMemidx(&destmemidx, "memory.copy destmemindex"));
+ }
+ CALLBACK(OnMemoryCopyExpr, srcmemidx, destmemidx);
+ CALLBACK(OnOpcodeUint32Uint32, srcmemidx, destmemidx);
break;
}
diff --git a/src/binary-reader.h b/src/binary-reader.h
index ff954d9d..a10fa395 100644
--- a/src/binary-reader.h
+++ b/src/binary-reader.h
@@ -251,18 +251,19 @@ class BinaryReaderDelegate {
virtual Result OnI64ConstExpr(uint64_t value) = 0;
virtual Result OnIfExpr(Type sig_type) = 0;
virtual Result OnLoadExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) = 0;
virtual Result OnLocalGetExpr(Index local_index) = 0;
virtual Result OnLocalSetExpr(Index local_index) = 0;
virtual Result OnLocalTeeExpr(Index local_index) = 0;
virtual Result OnLoopExpr(Type sig_type) = 0;
- virtual Result OnMemoryCopyExpr() = 0;
+ virtual Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) = 0;
virtual Result OnDataDropExpr(Index segment_index) = 0;
- virtual Result OnMemoryFillExpr() = 0;
- virtual Result OnMemoryGrowExpr() = 0;
- virtual Result OnMemoryInitExpr(Index segment_index) = 0;
- virtual Result OnMemorySizeExpr() = 0;
+ virtual Result OnMemoryFillExpr(Index memidx) = 0;
+ virtual Result OnMemoryGrowExpr(Index memidx) = 0;
+ virtual Result OnMemoryInitExpr(Index segment_index, Index memidx) = 0;
+ virtual Result OnMemorySizeExpr(Index memidx) = 0;
virtual Result OnTableCopyExpr(Index dst_index, Index src_index) = 0;
virtual Result OnElemDropExpr(Index segment_index) = 0;
virtual Result OnTableInitExpr(Index segment_index, Index table_index) = 0;
@@ -282,6 +283,7 @@ class BinaryReaderDelegate {
Index table_index) = 0;
virtual Result OnSelectExpr(Index result_count, Type* result_types) = 0;
virtual Result OnStoreExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) = 0;
virtual Result OnThrowExpr(Index tag_index) = 0;
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index d78d98df..c3adfbf6 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -386,7 +386,13 @@ class BinaryWriter {
template <typename T>
void WriteLoadStoreExpr(const Func* func, const Expr* expr, const char* desc);
template <typename T>
- void WriteSimdLoadStoreLaneExpr(const Func* func, const Expr* expr, const char* desc);
+ void WriteMemoryLoadStoreExpr(const Func* func,
+ const Expr* expr,
+ const char* desc);
+ template <typename T>
+ void WriteSimdLoadStoreLaneExpr(const Func* func,
+ const Expr* expr,
+ const char* desc);
void WriteExpr(const Func* func, const Expr* expr);
void WriteExprList(const Func* func, const ExprList& exprs);
void WriteInitExpr(const ExprList& expr);
@@ -659,6 +665,24 @@ void BinaryWriter::WriteLoadStoreExpr(const Func* func,
}
template <typename T>
+void BinaryWriter::WriteMemoryLoadStoreExpr(const Func* func,
+ const Expr* expr,
+ const char* desc) {
+ auto* typed_expr = cast<T>(expr);
+ WriteOpcode(stream_, typed_expr->opcode);
+ Address align = typed_expr->opcode.GetAlignment(typed_expr->align);
+ Index memidx = module_->GetMemoryIndex(typed_expr->memidx);
+ if (memidx != 0) {
+ stream_->WriteU8(log2_u32(align) | (1 << 6), "alignment");
+ WriteU32Leb128(stream_, typed_expr->offset, desc);
+ WriteU32Leb128(stream_, memidx, "memidx");
+ } else {
+ stream_->WriteU8(log2_u32(align), "alignment");
+ WriteU32Leb128(stream_, typed_expr->offset, desc);
+ }
+};
+
+template <typename T>
void BinaryWriter::WriteSimdLoadStoreLaneExpr(const Func* func,
const Expr* expr,
const char* desc) {
@@ -828,7 +852,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
break;
}
case ExprType::Load:
- WriteLoadStoreExpr<LoadExpr>(func, expr, "load offset");
+ WriteMemoryLoadStoreExpr<LoadExpr>(func, expr, "load offset");
break;
case ExprType::LocalGet: {
Index index = GetLocalIndex(func, cast<LocalGetExpr>(expr)->var);
@@ -854,11 +878,16 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
WriteExprList(func, cast<LoopExpr>(expr)->block.exprs);
WriteOpcode(stream_, Opcode::End);
break;
- case ExprType::MemoryCopy:
+ case ExprType::MemoryCopy: {
+ Index srcmemidx =
+ module_->GetMemoryIndex(cast<MemoryCopyExpr>(expr)->srcmemidx);
+ Index destmemidx =
+ module_->GetMemoryIndex(cast<MemoryCopyExpr>(expr)->destmemidx);
WriteOpcode(stream_, Opcode::MemoryCopy);
- WriteU32Leb128(stream_, 0, "memory.copy reserved");
- WriteU32Leb128(stream_, 0, "memory.copy reserved");
+ WriteU32Leb128(stream_, srcmemidx, "memory.copy srcmemidx");
+ WriteU32Leb128(stream_, destmemidx, "memory.copy destmemidx");
break;
+ }
case ExprType::DataDrop: {
Index index =
module_->GetDataSegmentIndex(cast<DataDropExpr>(expr)->var);
@@ -867,27 +896,38 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
has_data_segment_instruction_ = true;
break;
}
- case ExprType::MemoryFill:
+ case ExprType::MemoryFill: {
+ Index memidx =
+ module_->GetMemoryIndex(cast<MemoryFillExpr>(expr)->memidx);
WriteOpcode(stream_, Opcode::MemoryFill);
- WriteU32Leb128(stream_, 0, "memory.fill reserved");
+ WriteU32Leb128(stream_, memidx, "memory.fill memidx");
break;
- case ExprType::MemoryGrow:
+ }
+ case ExprType::MemoryGrow: {
+ Index memidx =
+ module_->GetMemoryIndex(cast<MemoryGrowExpr>(expr)->memidx);
WriteOpcode(stream_, Opcode::MemoryGrow);
- WriteU32Leb128(stream_, 0, "memory.grow reserved");
+ WriteU32Leb128(stream_, memidx, "memory.grow memidx");
break;
+ }
case ExprType::MemoryInit: {
Index index =
module_->GetDataSegmentIndex(cast<MemoryInitExpr>(expr)->var);
+ Index memidx =
+ module_->GetMemoryIndex(cast<MemoryInitExpr>(expr)->memidx);
WriteOpcode(stream_, Opcode::MemoryInit);
WriteU32Leb128(stream_, index, "memory.init segment");
- WriteU32Leb128(stream_, 0, "memory.init reserved");
+ WriteU32Leb128(stream_, memidx, "memory.init memidx");
has_data_segment_instruction_ = true;
break;
}
- case ExprType::MemorySize:
+ case ExprType::MemorySize: {
+ Index memidx =
+ module_->GetMemoryIndex(cast<MemorySizeExpr>(expr)->memidx);
WriteOpcode(stream_, Opcode::MemorySize);
- WriteU32Leb128(stream_, 0, "memory.size reserved");
+ WriteU32Leb128(stream_, memidx, "memory.size memidx");
break;
+ }
case ExprType::TableCopy: {
auto* copy_expr = cast<TableCopyExpr>(expr);
Index dst = module_->GetTableIndex(copy_expr->dst_table);
@@ -989,7 +1029,7 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
break;
}
case ExprType::Store:
- WriteLoadStoreExpr<StoreExpr>(func, expr, "store offset");
+ WriteMemoryLoadStoreExpr<StoreExpr>(func, expr, "store offset");
break;
case ExprType::Throw:
WriteOpcode(stream_, Opcode::Throw);
@@ -1591,7 +1631,13 @@ Result BinaryWriter::WriteModule() {
uint8_t flags = segment->GetFlags(module_);
stream_->WriteU8(flags, "segment flags");
if (!(flags & SegPassive)) {
- assert(module_->GetMemoryIndex(segment->memory_var) == 0);
+ if (options_.features.multi_memory_enabled() &&
+ (flags & SegExplicitIndex)) {
+ WriteU32Leb128(stream_, module_->GetMemoryIndex(segment->memory_var),
+ "memidx");
+ } else {
+ assert(module_->GetMemoryIndex(segment->memory_var) == 0);
+ }
WriteInitExpr(segment->offset);
}
WriteU32Leb128(stream_, segment->data.size(), "data segment size");
diff --git a/src/c-writer.cc b/src/c-writer.cc
index df8c037b..d4381a6e 100644
--- a/src/c-writer.cc
+++ b/src/c-writer.cc
@@ -1001,7 +1001,6 @@ void CWriter::WriteMemories() {
Write(Newline());
- assert(module_->memories.size() <= 1);
Index memory_index = 0;
for (const Memory* memory : module_->memories) {
bool is_import = memory_index < module_->num_memory_imports;
@@ -1069,11 +1068,15 @@ void CWriter::WriteDataInitializers() {
}
Write(Newline(), "static void init_memory(void) ", OpenBrace());
- if (memory && module_->num_memory_imports == 0) {
- uint32_t max =
- memory->page_limits.has_max ? memory->page_limits.max : 65536;
- Write("wasm_rt_allocate_memory(", ExternalPtr(memory->name), ", ",
- memory->page_limits.initial, ", ", max, ");", Newline());
+ if (module_->memories.size() > module_->num_memory_imports) {
+ Index memory_idx = module_->num_memory_imports;
+ for (Index i = memory_idx; i < module_->memories.size(); i++) {
+ memory = module_->memories[i];
+ uint32_t max =
+ memory->page_limits.has_max ? memory->page_limits.max : 65536;
+ Write("wasm_rt_allocate_memory(", ExternalPtr(memory->name), ", ",
+ memory->page_limits.initial, ", ", max, ");", Newline());
+ }
}
data_segment_index = 0;
for (const DataSegment* data_segment : module_->data_segments) {
@@ -1613,8 +1616,8 @@ void CWriter::Write(const ExprList& exprs) {
break;
case ExprType::MemoryGrow: {
- assert(module_->memories.size() == 1);
- Memory* memory = module_->memories[0];
+ Memory* memory = module_->memories[module_->GetMemoryIndex(
+ cast<MemoryGrowExpr>(&expr)->memidx)];
Write(StackVar(0), " = wasm_rt_grow_memory(", ExternalPtr(memory->name),
", ", StackVar(0), ");", Newline());
@@ -1622,8 +1625,8 @@ void CWriter::Write(const ExprList& exprs) {
}
case ExprType::MemorySize: {
- assert(module_->memories.size() == 1);
- Memory* memory = module_->memories[0];
+ Memory* memory = module_->memories[module_->GetMemoryIndex(
+ cast<MemorySizeExpr>(&expr)->memidx)];
PushType(Type::I32);
Write(StackVar(0), " = ", ExternalRef(memory->name), ".pages;",
@@ -2119,8 +2122,7 @@ void CWriter::Write(const LoadExpr& expr) {
WABT_UNREACHABLE;
}
- assert(module_->memories.size() == 1);
- Memory* memory = module_->memories[0];
+ Memory* memory = module_->memories[module_->GetMemoryIndex(expr.memidx)];
Type result_type = expr.opcode.GetResultType();
Write(StackVar(0, result_type), " = ", func, "(", ExternalPtr(memory->name),
@@ -2149,8 +2151,7 @@ void CWriter::Write(const StoreExpr& expr) {
WABT_UNREACHABLE;
}
- assert(module_->memories.size() == 1);
- Memory* memory = module_->memories[0];
+ Memory* memory = module_->memories[module_->GetMemoryIndex(expr.memidx)];
Write(func, "(", ExternalPtr(memory->name), ", (u64)(", StackVar(1), ")");
if (expr.offset != 0)
diff --git a/src/feature.def b/src/feature.def
index 238e8518..cecab3e6 100644
--- a/src/feature.def
+++ b/src/feature.def
@@ -36,3 +36,4 @@ WABT_FEATURE(reference_types, "reference-types", true, "Reference
WABT_FEATURE(annotations, "annotations", false, "Custom annotation syntax")
WABT_FEATURE(gc, "gc", false, "Garbage collection")
WABT_FEATURE(memory64, "memory64", false, "64-bit memory")
+WABT_FEATURE(multi_memory, "multi-memory", false, "Multi-memory")
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index eaae9f1b..0cec0c21 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -196,19 +196,20 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnI64ConstExpr(uint64_t value) override;
Result OnIfExpr(Type sig_type) override;
Result OnLoadExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) override;
Result OnLocalGetExpr(Index local_index) override;
Result OnLocalSetExpr(Index local_index) override;
Result OnLocalTeeExpr(Index local_index) override;
Result OnLoopExpr(Type sig_type) override;
- Result OnMemoryCopyExpr() override;
+ Result OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) override;
Result OnDataDropExpr(Index segment_index) override;
- Result OnMemoryGrowExpr() override;
- Result OnMemoryFillExpr() override;
- Result OnMemoryInitExpr(Index segment_index) override;
- Result OnMemorySizeExpr() override;
- Result OnRefFuncExpr(Index type_index) override;
+ Result OnMemoryGrowExpr(Index memidx) override;
+ Result OnMemoryFillExpr(Index memidx) override;
+ Result OnMemoryInitExpr(Index segment_index, Index memidx) override;
+ Result OnMemorySizeExpr(Index memidx) override;
+ Result OnRefFuncExpr(Index func_index) override;
Result OnRefNullExpr(Type type) override;
Result OnRefIsNullExpr() override;
Result OnNopExpr() override;
@@ -216,6 +217,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
Result OnReturnExpr() override;
Result OnSelectExpr(Index result_count, Type* result_types) override;
Result OnStoreExpr(Opcode opcode,
+ Index memidx,
Address alignment_log2,
Address offset) override;
Result OnUnaryExpr(Opcode opcode) override;
@@ -1331,30 +1333,34 @@ Result BinaryReaderInterp::OnLocalTeeExpr(Index local_index) {
}
Result BinaryReaderInterp::OnLoadExpr(Opcode opcode,
+ Index memidx,
Address align_log2,
Address offset) {
- CHECK_RESULT(validator_.OnLoad(loc, opcode, GetAlignment(align_log2)));
- istream_.Emit(opcode, kMemoryIndex0, offset);
+ CHECK_RESULT(
+ validator_.OnLoad(loc, opcode, Var(memidx), GetAlignment(align_log2)));
+ istream_.Emit(opcode, memidx, offset);
return Result::Ok;
}
Result BinaryReaderInterp::OnStoreExpr(Opcode opcode,
+ Index memidx,
Address align_log2,
Address offset) {
- CHECK_RESULT(validator_.OnStore(loc, opcode, GetAlignment(align_log2)));
- istream_.Emit(opcode, kMemoryIndex0, offset);
+ CHECK_RESULT(
+ validator_.OnStore(loc, opcode, Var(memidx), GetAlignment(align_log2)));
+ istream_.Emit(opcode, memidx, offset);
return Result::Ok;
}
-Result BinaryReaderInterp::OnMemoryGrowExpr() {
- CHECK_RESULT(validator_.OnMemoryGrow(loc));
- istream_.Emit(Opcode::MemoryGrow, kMemoryIndex0);
+Result BinaryReaderInterp::OnMemoryGrowExpr(Index memidx) {
+ CHECK_RESULT(validator_.OnMemoryGrow(loc, Var(memidx)));
+ istream_.Emit(Opcode::MemoryGrow, memidx);
return Result::Ok;
}
-Result BinaryReaderInterp::OnMemorySizeExpr() {
- CHECK_RESULT(validator_.OnMemorySize(loc));
- istream_.Emit(Opcode::MemorySize, kMemoryIndex0);
+Result BinaryReaderInterp::OnMemorySizeExpr(Index memidx) {
+ CHECK_RESULT(validator_.OnMemorySize(loc, Var(memidx)));
+ istream_.Emit(Opcode::MemorySize, memidx);
return Result::Ok;
}
@@ -1447,9 +1453,9 @@ Result BinaryReaderInterp::OnAtomicNotifyExpr(Opcode opcode,
return Result::Ok;
}
-Result BinaryReaderInterp::OnMemoryCopyExpr() {
- CHECK_RESULT(validator_.OnMemoryCopy(loc));
- istream_.Emit(Opcode::MemoryCopy, kMemoryIndex0, kMemoryIndex0);
+Result BinaryReaderInterp::OnMemoryCopyExpr(Index srcmemidx, Index destmemidx) {
+ CHECK_RESULT(validator_.OnMemoryCopy(loc, Var(srcmemidx), Var(destmemidx)));
+ istream_.Emit(Opcode::MemoryCopy, srcmemidx, destmemidx);
return Result::Ok;
}
@@ -1459,15 +1465,15 @@ Result BinaryReaderInterp::OnDataDropExpr(Index segment_index) {
return Result::Ok;
}
-Result BinaryReaderInterp::OnMemoryFillExpr() {
- CHECK_RESULT(validator_.OnMemoryFill(loc));
- istream_.Emit(Opcode::MemoryFill, kMemoryIndex0);
+Result BinaryReaderInterp::OnMemoryFillExpr(Index memidx) {
+ CHECK_RESULT(validator_.OnMemoryFill(loc, Var(memidx)));
+ istream_.Emit(Opcode::MemoryFill, memidx);
return Result::Ok;
}
-Result BinaryReaderInterp::OnMemoryInitExpr(Index segment_index) {
- CHECK_RESULT(validator_.OnMemoryInit(loc, Var(segment_index)));
- istream_.Emit(Opcode::MemoryInit, kMemoryIndex0, segment_index);
+Result BinaryReaderInterp::OnMemoryInitExpr(Index segment_index, Index memidx) {
+ CHECK_RESULT(validator_.OnMemoryInit(loc, Var(segment_index), Var(memidx)));
+ istream_.Emit(Opcode::MemoryInit, memidx, segment_index);
return Result::Ok;
}
diff --git a/src/ir.h b/src/ir.h
index 286a4420..31597d40 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -418,15 +418,40 @@ class ExprMixin : public Expr {
explicit ExprMixin(const Location& loc = Location()) : Expr(TypeEnum, loc) {}
};
+template <ExprType TypeEnum>
+class MemoryExpr : public ExprMixin<TypeEnum> {
+ public:
+ MemoryExpr(Var memidx, const Location& loc = Location())
+ : ExprMixin<TypeEnum>(loc), memidx(memidx) {}
+
+ Var memidx;
+};
+
+template <ExprType TypeEnum>
+class MemoryBinaryExpr : public ExprMixin<TypeEnum> {
+ public:
+ MemoryBinaryExpr(Var srcmemidx,
+ Var destmemidx,
+ const Location& loc = Location())
+ : ExprMixin<TypeEnum>(loc),
+ srcmemidx(srcmemidx),
+ destmemidx(destmemidx) {}
+
+ Var srcmemidx;
+ Var destmemidx;
+};
+
typedef ExprMixin<ExprType::Drop> DropExpr;
-typedef ExprMixin<ExprType::MemoryGrow> MemoryGrowExpr;
-typedef ExprMixin<ExprType::MemorySize> MemorySizeExpr;
-typedef ExprMixin<ExprType::MemoryCopy> MemoryCopyExpr;
-typedef ExprMixin<ExprType::MemoryFill> MemoryFillExpr;
typedef ExprMixin<ExprType::Nop> NopExpr;
typedef ExprMixin<ExprType::Return> ReturnExpr;
typedef ExprMixin<ExprType::Unreachable> UnreachableExpr;
+typedef MemoryExpr<ExprType::MemoryGrow> MemoryGrowExpr;
+typedef MemoryExpr<ExprType::MemorySize> MemorySizeExpr;
+typedef MemoryExpr<ExprType::MemoryFill> MemoryFillExpr;
+
+typedef MemoryBinaryExpr<ExprType::MemoryCopy> MemoryCopyExpr;
+
template <ExprType TypeEnum>
class RefTypeExpr : public ExprMixin<TypeEnum> {
public:
@@ -515,6 +540,15 @@ class VarExpr : public ExprMixin<TypeEnum> {
Var var;
};
+template <ExprType TypeEnum>
+class MemoryVarExpr : public MemoryExpr<TypeEnum> {
+ public:
+ MemoryVarExpr(const Var& var, Var memidx, const Location& loc = Location())
+ : MemoryExpr<TypeEnum>(memidx, loc), var(var) {}
+
+ Var var;
+};
+
typedef VarExpr<ExprType::Br> BrExpr;
typedef VarExpr<ExprType::BrIf> BrIfExpr;
typedef VarExpr<ExprType::Call> CallExpr;
@@ -528,7 +562,6 @@ typedef VarExpr<ExprType::ReturnCall> ReturnCallExpr;
typedef VarExpr<ExprType::Throw> ThrowExpr;
typedef VarExpr<ExprType::Rethrow> RethrowExpr;
-typedef VarExpr<ExprType::MemoryInit> MemoryInitExpr;
typedef VarExpr<ExprType::DataDrop> DataDropExpr;
typedef VarExpr<ExprType::ElemDrop> ElemDropExpr;
typedef VarExpr<ExprType::TableGet> TableGetExpr;
@@ -537,6 +570,8 @@ typedef VarExpr<ExprType::TableGrow> TableGrowExpr;
typedef VarExpr<ExprType::TableSize> TableSizeExpr;
typedef VarExpr<ExprType::TableFill> TableFillExpr;
+typedef MemoryVarExpr<ExprType::MemoryInit> MemoryInitExpr;
+
class SelectExpr : public ExprMixin<ExprType::Select> {
public:
SelectExpr(TypeVector type, const Location& loc = Location())
@@ -664,8 +699,27 @@ class LoadStoreExpr : public ExprMixin<TypeEnum> {
Address offset;
};
-typedef LoadStoreExpr<ExprType::Load> LoadExpr;
-typedef LoadStoreExpr<ExprType::Store> StoreExpr;
+template <ExprType TypeEnum>
+class MemoryLoadStoreExpr : public MemoryExpr<TypeEnum> {
+ public:
+ MemoryLoadStoreExpr(Opcode opcode,
+ Var memidx,
+ Address align,
+ Address offset,
+ const Location& loc = Location())
+ : MemoryExpr<TypeEnum>(memidx, loc),
+ opcode(opcode),
+ align(align),
+ offset(offset) {}
+
+ Opcode opcode;
+ Address align;
+ Address offset;
+};
+
+typedef MemoryLoadStoreExpr<ExprType::Load> LoadExpr;
+typedef MemoryLoadStoreExpr<ExprType::Store> StoreExpr;
+
typedef LoadStoreExpr<ExprType::AtomicLoad> AtomicLoadExpr;
typedef LoadStoreExpr<ExprType::AtomicStore> AtomicStoreExpr;
typedef LoadStoreExpr<ExprType::AtomicRmw> AtomicRmwExpr;
diff --git a/src/resolve-names.cc b/src/resolve-names.cc
index abd554ff..4c4c1495 100644
--- a/src/resolve-names.cc
+++ b/src/resolve-names.cc
@@ -51,13 +51,18 @@ class NameResolver : public ExprVisitor::DelegateNop {
Result OnGlobalSetExpr(GlobalSetExpr*) override;
Result BeginIfExpr(IfExpr*) override;
Result EndIfExpr(IfExpr*) override;
+ Result OnLoadExpr(LoadExpr*) override;
Result OnLocalGetExpr(LocalGetExpr*) override;
Result OnLocalSetExpr(LocalSetExpr*) override;
Result OnLocalTeeExpr(LocalTeeExpr*) override;
Result BeginLoopExpr(LoopExpr*) override;
Result EndLoopExpr(LoopExpr*) override;
+ Result OnMemoryCopyExpr(MemoryCopyExpr*) override;
Result OnDataDropExpr(DataDropExpr*) override;
+ Result OnMemoryFillExpr(MemoryFillExpr*) override;
+ Result OnMemoryGrowExpr(MemoryGrowExpr*) override;
Result OnMemoryInitExpr(MemoryInitExpr*) override;
+ Result OnMemorySizeExpr(MemorySizeExpr*) override;
Result OnElemDropExpr(ElemDropExpr*) override;
Result OnTableCopyExpr(TableCopyExpr*) override;
Result OnTableInitExpr(TableInitExpr*) override;
@@ -67,6 +72,7 @@ class NameResolver : public ExprVisitor::DelegateNop {
Result OnTableSizeExpr(TableSizeExpr*) override;
Result OnTableFillExpr(TableFillExpr*) override;
Result OnRefFuncExpr(RefFuncExpr*) override;
+ Result OnStoreExpr(StoreExpr*) override;
Result BeginTryExpr(TryExpr*) override;
Result EndTryExpr(TryExpr*) override;
Result OnThrowExpr(ThrowExpr*) override;
@@ -321,6 +327,11 @@ Result NameResolver::EndIfExpr(IfExpr* expr) {
return Result::Ok;
}
+Result NameResolver::OnLoadExpr(LoadExpr* expr) {
+ ResolveMemoryVar(&expr->memidx);
+ return Result::Ok;
+}
+
Result NameResolver::OnLocalGetExpr(LocalGetExpr* expr) {
ResolveLocalVar(&expr->var);
return Result::Ok;
@@ -336,13 +347,35 @@ Result NameResolver::OnLocalTeeExpr(LocalTeeExpr* expr) {
return Result::Ok;
}
+Result NameResolver::OnMemoryCopyExpr(MemoryCopyExpr* expr) {
+ ResolveMemoryVar(&expr->srcmemidx);
+ ResolveMemoryVar(&expr->destmemidx);
+ return Result::Ok;
+}
+
Result NameResolver::OnDataDropExpr(DataDropExpr* expr) {
ResolveDataSegmentVar(&expr->var);
return Result::Ok;
}
+Result NameResolver::OnMemoryFillExpr(MemoryFillExpr* expr) {
+ ResolveMemoryVar(&expr->memidx);
+ return Result::Ok;
+}
+
+Result NameResolver::OnMemoryGrowExpr(MemoryGrowExpr* expr) {
+ ResolveMemoryVar(&expr->memidx);
+ return Result::Ok;
+}
+
Result NameResolver::OnMemoryInitExpr(MemoryInitExpr* expr) {
ResolveDataSegmentVar(&expr->var);
+ ResolveMemoryVar(&expr->memidx);
+ return Result::Ok;
+}
+
+Result NameResolver::OnMemorySizeExpr(MemorySizeExpr* expr) {
+ ResolveMemoryVar(&expr->memidx);
return Result::Ok;
}
@@ -393,6 +426,11 @@ Result NameResolver::OnRefFuncExpr(RefFuncExpr* expr) {
return Result::Ok;
}
+Result NameResolver::OnStoreExpr(StoreExpr* expr) {
+ ResolveMemoryVar(&expr->memidx);
+ return Result::Ok;
+}
+
Result NameResolver::BeginTryExpr(TryExpr* expr) {
PushLabel(expr->block.label);
ResolveBlockDeclarationVar(&expr->block.decl);
diff --git a/src/shared-validator.cc b/src/shared-validator.cc
index 071a1c0f..2a5a4a8e 100644
--- a/src/shared-validator.cc
+++ b/src/shared-validator.cc
@@ -135,7 +135,7 @@ Result SharedValidator::OnTable(const Location& loc,
Result SharedValidator::OnMemory(const Location& loc, const Limits& limits) {
Result result = Result::Ok;
- if (memories_.size() > 0) {
+ if (memories_.size() > 0 && !options_.features.multi_memory_enabled()) {
result |= PrintError(loc, "only one memory block allowed");
}
result |= CheckLimits(
@@ -903,11 +903,12 @@ Result SharedValidator::OnIf(const Location& loc, Type sig_type) {
Result SharedValidator::OnLoad(const Location& loc,
Opcode opcode,
+ Var memidx,
Address alignment) {
Result result = Result::Ok;
MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= CheckMemoryIndex(memidx, &mt);
result |= CheckAlign(loc, alignment, opcode.GetMemorySize());
result |= typechecker_.OnLoad(opcode, mt.limits);
return result;
@@ -974,16 +975,19 @@ Result SharedValidator::OnLoop(const Location& loc, Type sig_type) {
return result;
}
-Result SharedValidator::OnMemoryCopy(const Location& loc) {
+Result SharedValidator::OnMemoryCopy(const Location& loc,
+ Var srcmemidx,
+ Var destmemidx) {
Result result = Result::Ok;
MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= CheckMemoryIndex(srcmemidx, &mt);
+ result |= CheckMemoryIndex(destmemidx, &mt);
result |= typechecker_.OnMemoryCopy(mt.limits);
return result;
}
-Result SharedValidator::OnMemoryFill(const Location& loc) {
+Result SharedValidator::OnMemoryFill(const Location& loc, Var memidx) {
Result result = Result::Ok;
MemoryType mt;
expr_loc_ = &loc;
@@ -992,30 +996,32 @@ Result SharedValidator::OnMemoryFill(const Location& loc) {
return result;
}
-Result SharedValidator::OnMemoryGrow(const Location& loc) {
+Result SharedValidator::OnMemoryGrow(const Location& loc, Var memidx) {
Result result = Result::Ok;
MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= CheckMemoryIndex(memidx, &mt);
result |= typechecker_.OnMemoryGrow(mt.limits);
return result;
}
-Result SharedValidator::OnMemoryInit(const Location& loc, Var segment_var) {
+Result SharedValidator::OnMemoryInit(const Location& loc,
+ Var segment_var,
+ Var memidx) {
Result result = Result::Ok;
MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= CheckMemoryIndex(memidx, &mt);
result |= CheckDataSegmentIndex(segment_var);
result |= typechecker_.OnMemoryInit(segment_var.index(), mt.limits);
return result;
}
-Result SharedValidator::OnMemorySize(const Location& loc) {
+Result SharedValidator::OnMemorySize(const Location& loc, Var memidx) {
Result result = Result::Ok;
MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= CheckMemoryIndex(memidx, &mt);
result |= typechecker_.OnMemorySize(mt.limits);
return result;
}
@@ -1144,11 +1150,12 @@ Result SharedValidator::OnSimdShuffleOp(const Location& loc,
Result SharedValidator::OnStore(const Location& loc,
Opcode opcode,
+ Var memidx,
Address alignment) {
Result result = Result::Ok;
MemoryType mt;
expr_loc_ = &loc;
- result |= CheckMemoryIndex(Var(0, loc), &mt);
+ result |= CheckMemoryIndex(memidx, &mt);
result |= CheckAlign(loc, alignment, opcode.GetMemorySize());
result |= typechecker_.OnStore(opcode, mt.limits);
return result;
diff --git a/src/shared-validator.h b/src/shared-validator.h
index 3bc02ff3..9c28af74 100644
--- a/src/shared-validator.h
+++ b/src/shared-validator.h
@@ -142,18 +142,18 @@ class SharedValidator {
Result OnGlobalGet(const Location&, Var);
Result OnGlobalSet(const Location&, Var);
Result OnIf(const Location&, Type sig_type);
- Result OnLoad(const Location&, Opcode, Address align);
+ Result OnLoad(const Location&, Opcode, Var memidx, Address align);
Result OnLoadSplat(const Location&, Opcode, Address align);
Result OnLoadZero(const Location&, Opcode, Address align);
Result OnLocalGet(const Location&, Var);
Result OnLocalSet(const Location&, Var);
Result OnLocalTee(const Location&, Var);
Result OnLoop(const Location&, Type sig_type);
- Result OnMemoryCopy(const Location&);
- Result OnMemoryFill(const Location&);
- Result OnMemoryGrow(const Location&);
- Result OnMemoryInit(const Location&, Var segment_var);
- Result OnMemorySize(const Location&);
+ Result OnMemoryCopy(const Location&, Var srcmemidx, Var destmemidx);
+ Result OnMemoryFill(const Location&, Var memidx);
+ Result OnMemoryGrow(const Location&, Var memidx);
+ Result OnMemoryInit(const Location&, Var segment_var, Var memidx);
+ Result OnMemorySize(const Location&, Var memidx);
Result OnNop(const Location&);
Result OnRefFunc(const Location&, Var func_var);
Result OnRefIsNull(const Location&);
@@ -167,7 +167,7 @@ class SharedValidator {
Result OnSimdLoadLane(const Location&, Opcode, Address align, uint64_t lane_idx);
Result OnSimdStoreLane(const Location&, Opcode, Address align, uint64_t lane_idx);
Result OnSimdShuffleOp(const Location&, Opcode, v128 lane_idx);
- Result OnStore(const Location&, Opcode, Address align);
+ Result OnStore(const Location&, Opcode, Var memidx, Address align);
Result OnTableCopy(const Location&, Var dst_var, Var src_var);
Result OnTableFill(const Location&, Var table_var);
Result OnTableGet(const Location&, Var table_var);
diff --git a/src/validator.cc b/src/validator.cc
index 672f698b..75c06211 100644
--- a/src/validator.cc
+++ b/src/validator.cc
@@ -334,7 +334,7 @@ Result Validator::EndIfExpr(IfExpr* expr) {
}
Result Validator::OnLoadExpr(LoadExpr* expr) {
- result_ |= validator_.OnLoad(expr->loc, expr->opcode,
+ result_ |= validator_.OnLoad(expr->loc, expr->opcode, expr->memidx,
expr->opcode.GetAlignment(expr->align));
return Result::Ok;
}
@@ -365,7 +365,8 @@ Result Validator::EndLoopExpr(LoopExpr* expr) {
}
Result Validator::OnMemoryCopyExpr(MemoryCopyExpr* expr) {
- result_ |= validator_.OnMemoryCopy(expr->loc);
+ result_ |=
+ validator_.OnMemoryCopy(expr->loc, expr->srcmemidx, expr->destmemidx);
return Result::Ok;
}
@@ -375,22 +376,22 @@ Result Validator::OnDataDropExpr(DataDropExpr* expr) {
}
Result Validator::OnMemoryFillExpr(MemoryFillExpr* expr) {
- result_ |= validator_.OnMemoryFill(expr->loc);
+ result_ |= validator_.OnMemoryFill(expr->loc, expr->memidx);
return Result::Ok;
}
Result Validator::OnMemoryGrowExpr(MemoryGrowExpr* expr) {
- result_ |= validator_.OnMemoryGrow(expr->loc);
+ result_ |= validator_.OnMemoryGrow(expr->loc, expr->memidx);
return Result::Ok;
}
Result Validator::OnMemoryInitExpr(MemoryInitExpr* expr) {
- result_ |= validator_.OnMemoryInit(expr->loc, expr->var);
+ result_ |= validator_.OnMemoryInit(expr->loc, expr->var, expr->memidx);
return Result::Ok;
}
Result Validator::OnMemorySizeExpr(MemorySizeExpr* expr) {
- result_ |= validator_.OnMemorySize(expr->loc);
+ result_ |= validator_.OnMemorySize(expr->loc, expr->memidx);
return Result::Ok;
}
@@ -484,7 +485,7 @@ Result Validator::OnSelectExpr(SelectExpr* expr) {
}
Result Validator::OnStoreExpr(StoreExpr* expr) {
- result_ |= validator_.OnStore(expr->loc, expr->opcode,
+ result_ |= validator_.OnStore(expr->loc, expr->opcode, expr->memidx,
expr->opcode.GetAlignment(expr->align));
return Result::Ok;
}
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index d12cbc44..79436fc1 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -1024,6 +1024,27 @@ bool WastParser::ParseAlignOpt(Address* out_align) {
}
}
+Result WastParser::ParseMemidx(Location loc, Var* out_memidx) {
+ WABT_TRACE(ParseMemidx);
+ if (PeekMatchLpar(TokenType::Memory)) {
+ if (!options_->features.multi_memory_enabled()) {
+ Error(loc, "Specifying memory variable is not allowed");
+ return Result::Error;
+ }
+ EXPECT(Lpar);
+ EXPECT(Memory);
+ CHECK_RESULT(ParseVar(out_memidx));
+ EXPECT(Rpar);
+ } else {
+ if (ParseVarOpt(out_memidx, Var(0, loc)) &&
+ !options_->features.multi_memory_enabled()) {
+ Error(loc, "Specifying memory variable is not allowed");
+ return Result::Error;
+ }
+ }
+ return Result::Ok;
+}
+
Result WastParser::ParseLimitsIndex(Limits* out_limits) {
WABT_TRACE(ParseLimitsIndex);
@@ -1861,6 +1882,34 @@ Result WastParser::ParsePlainInstrVar(Location loc,
}
template <typename T>
+Result WastParser::ParseMemoryInstrVar(Location loc,
+ std::unique_ptr<Expr>* out_expr) {
+ Var memidx;
+ Var var;
+ if (PeekMatchLpar(TokenType::Memory)) {
+ if (!options_->features.multi_memory_enabled()) {
+ Error(loc, "Specifying memory variable is not allowed");
+ return Result::Error;
+ }
+ CHECK_RESULT(ParseMemidx(loc, &memidx));
+ CHECK_RESULT(ParseVar(&var));
+ out_expr->reset(new T(var, memidx, loc));
+ } else {
+ CHECK_RESULT(ParseVar(&memidx));
+ if (ParseVarOpt(&var, Var(0, loc))) {
+ if (!options_->features.multi_memory_enabled()) {
+ Error(loc, "Specifiying memory variable is not allowed");
+ return Result::Error;
+ }
+ out_expr->reset(new T(var, memidx, loc));
+ } else {
+ out_expr->reset(new T(memidx, var, loc));
+ }
+ }
+ return Result::Ok;
+}
+
+template <typename T>
Result WastParser::ParsePlainLoadStoreInstr(Location loc,
Token token,
std::unique_ptr<Expr>* out_expr) {
@@ -1873,6 +1922,41 @@ Result WastParser::ParsePlainLoadStoreInstr(Location loc,
return Result::Ok;
}
+template <typename T>
+Result WastParser::ParseMemoryLoadStoreInstr(Location loc,
+ Token token,
+ std::unique_ptr<Expr>* out_expr) {
+ Opcode opcode = token.opcode();
+ Var memidx;
+ Address offset;
+ Address align;
+ CHECK_RESULT(ParseMemidx(loc, &memidx));
+ ParseOffsetOpt(&offset);
+ ParseAlignOpt(&align);
+ out_expr->reset(new T(opcode, memidx, align, offset, loc));
+ return Result::Ok;
+}
+
+template <typename T>
+Result WastParser::ParseMemoryExpr(Location loc,
+ std::unique_ptr<Expr>* out_expr) {
+ Var memidx;
+ CHECK_RESULT(ParseMemidx(loc, &memidx));
+ out_expr->reset(new T(memidx, loc));
+ return Result::Ok;
+}
+
+template <typename T>
+Result WastParser::ParseMemoryBinaryExpr(Location loc,
+ std::unique_ptr<Expr>* out_expr) {
+ Var srcmemidx;
+ Var destmemidx;
+ CHECK_RESULT(ParseMemidx(loc, &srcmemidx));
+ CHECK_RESULT(ParseMemidx(loc, &destmemidx));
+ out_expr->reset(new T(srcmemidx, destmemidx, loc));
+ return Result::Ok;
+}
+
Result WastParser::ParseSimdLane(Location loc, uint64_t* lane_idx) {
if (!PeekMatch(TokenType::Nat) && !PeekMatch(TokenType::Int)) {
return ErrorExpected({"a natural number in range [0, 32)"});
@@ -2019,12 +2103,12 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) {
case TokenType::Load:
CHECK_RESULT(
- ParsePlainLoadStoreInstr<LoadExpr>(loc, Consume(), out_expr));
+ ParseMemoryLoadStoreInstr<LoadExpr>(loc, Consume(), out_expr));
break;
case TokenType::Store:
CHECK_RESULT(
- ParsePlainLoadStoreInstr<StoreExpr>(loc, Consume(), out_expr));
+ ParseMemoryLoadStoreInstr<StoreExpr>(loc, Consume(), out_expr));
break;
case TokenType::Const: {
@@ -2061,12 +2145,12 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) {
case TokenType::MemoryCopy:
ErrorUnlessOpcodeEnabled(Consume());
- out_expr->reset(new MemoryCopyExpr(loc));
+ CHECK_RESULT(ParseMemoryBinaryExpr<MemoryCopyExpr>(loc, out_expr));
break;
case TokenType::MemoryFill:
ErrorUnlessOpcodeEnabled(Consume());
- out_expr->reset(new MemoryFillExpr(loc));
+ CHECK_RESULT(ParseMemoryExpr<MemoryFillExpr>(loc, out_expr));
break;
case TokenType::DataDrop:
@@ -2076,17 +2160,17 @@ Result WastParser::ParsePlainInstr(std::unique_ptr<Expr>* out_expr) {
case TokenType::MemoryInit:
ErrorUnlessOpcodeEnabled(Consume());
- CHECK_RESULT(ParsePlainInstrVar<MemoryInitExpr>(loc, out_expr));
+ CHECK_RESULT(ParseMemoryInstrVar<MemoryInitExpr>(loc, out_expr));
break;
case TokenType::MemorySize:
Consume();
- out_expr->reset(new MemorySizeExpr(loc));
+ CHECK_RESULT(ParseMemoryExpr<MemorySizeExpr>(loc, out_expr));
break;
case TokenType::MemoryGrow:
Consume();
- out_expr->reset(new MemoryGrowExpr(loc));
+ CHECK_RESULT(ParseMemoryExpr<MemoryGrowExpr>(loc, out_expr));
break;
case TokenType::TableCopy: {
diff --git a/src/wast-parser.h b/src/wast-parser.h
index 1d304484..00285d31 100644
--- a/src/wast-parser.h
+++ b/src/wast-parser.h
@@ -143,6 +143,7 @@ class WastParser {
Result ParseQuotedText(std::string* text);
bool ParseOffsetOpt(Address* offset);
bool ParseAlignOpt(Address* align);
+ Result ParseMemidx(Location loc, Var* memidx);
Result ParseLimitsIndex(Limits*);
Result ParseLimits(Limits*);
Result ParseNat(uint64_t*, bool is_64);
@@ -203,7 +204,15 @@ class WastParser {
template <typename T>
Result ParsePlainInstrVar(Location, std::unique_ptr<Expr>*);
template <typename T>
+ Result ParseMemoryInstrVar(Location, std::unique_ptr<Expr>*);
+ template <typename T>
Result ParsePlainLoadStoreInstr(Location, Token, std::unique_ptr<Expr>*);
+ template <typename T>
+ Result ParseMemoryLoadStoreInstr(Location, Token, std::unique_ptr<Expr>*);
+ template <typename T>
+ Result ParseMemoryExpr(Location, std::unique_ptr<Expr>*);
+ template <typename T>
+ Result ParseMemoryBinaryExpr(Location, std::unique_ptr<Expr>*);
Result ParseSimdLane(Location, uint64_t*);
Result ParseCommandList(Script*, CommandPtrVector*);
diff --git a/src/wat-writer.cc b/src/wat-writer.cc
index 4f40fd2a..531cb5b9 100644
--- a/src/wat-writer.cc
+++ b/src/wat-writer.cc
@@ -122,6 +122,10 @@ class WatWriter : ModuleContext {
void WriteQuotedString(string_view str, NextChar next_char);
void WriteVar(const Var& var, NextChar next_char);
void WriteVarUnlessZero(const Var& var, NextChar next_char);
+ void WriteMemoryVarUnlessZero(const Var& memidx, NextChar next_char);
+ void WriteTwoMemoryVarsUnlessBothZero(const Var& srcmemidx,
+ const Var& destmemidx,
+ NextChar next_char);
void WriteBrVar(const Var& var, NextChar next_char);
void WriteRefKind(Type type, NextChar next_char);
void WriteType(Type type, NextChar next_char);
@@ -135,6 +139,8 @@ class WatWriter : ModuleContext {
void WriteExpr(const Expr* expr);
template <typename T>
void WriteLoadStoreExpr(const Expr* expr);
+ template <typename T>
+ void WriteMemoryLoadStoreExpr(const Expr* expr);
void WriteExprList(const ExprList& exprs);
void WriteInitExpr(const ExprList& expr);
template <typename T>
@@ -375,6 +381,27 @@ void WatWriter::WriteVarUnlessZero(const Var& var, NextChar next_char) {
}
}
+void WatWriter::WriteMemoryVarUnlessZero(const Var& memidx,
+ NextChar next_char) {
+ if (module.GetMemoryIndex(memidx) != 0) {
+ WriteVar(memidx, next_char);
+ } else {
+ next_char_ = next_char;
+ }
+}
+
+void WatWriter::WriteTwoMemoryVarsUnlessBothZero(const Var& srcmemidx,
+ const Var& destmemidx,
+ NextChar next_char) {
+ if (module.GetMemoryIndex(srcmemidx) != 0 ||
+ module.GetMemoryIndex(destmemidx) != 0) {
+ WriteVar(srcmemidx, NextChar::Space);
+ WriteVar(destmemidx, next_char);
+ } else {
+ next_char_ = next_char;
+ }
+}
+
void WatWriter::WriteBrVar(const Var& var, NextChar next_char) {
if (var.is_index()) {
if (var.index() < GetLabelStackSize()) {
@@ -504,6 +531,20 @@ void WatWriter::WriteLoadStoreExpr(const Expr* expr) {
WriteNewline(NO_FORCE_NEWLINE);
}
+template <typename T>
+void WatWriter::WriteMemoryLoadStoreExpr(const Expr* expr) {
+ auto typed_expr = cast<T>(expr);
+ WritePutsSpace(typed_expr->opcode.GetName());
+ WriteMemoryVarUnlessZero(typed_expr->memidx, NextChar::Space);
+ if (typed_expr->offset) {
+ Writef("offset=%" PRIaddress, typed_expr->offset);
+ }
+ if (!typed_expr->opcode.IsNaturallyAligned(typed_expr->align)) {
+ Writef("align=%" PRIaddress, typed_expr->align);
+ }
+ WriteNewline(NO_FORCE_NEWLINE);
+}
+
class WatWriter::ExprVisitorDelegate : public ExprVisitor::Delegate {
public:
explicit ExprVisitorDelegate(WatWriter* writer) : writer_(writer) {}
@@ -695,7 +736,7 @@ Result WatWriter::ExprVisitorDelegate::EndIfExpr(IfExpr* expr) {
}
Result WatWriter::ExprVisitorDelegate::OnLoadExpr(LoadExpr* expr) {
- writer_->WriteLoadStoreExpr<LoadExpr>(expr);
+ writer_->WriteMemoryLoadStoreExpr<LoadExpr>(expr);
return Result::Ok;
}
@@ -729,7 +770,10 @@ Result WatWriter::ExprVisitorDelegate::EndLoopExpr(LoopExpr* expr) {
}
Result WatWriter::ExprVisitorDelegate::OnMemoryCopyExpr(MemoryCopyExpr* expr) {
- writer_->WritePutsNewline(Opcode::MemoryCopy_Opcode.GetName());
+ writer_->WritePutsSpace(Opcode::MemoryCopy_Opcode.GetName());
+ writer_->WriteTwoMemoryVarsUnlessBothZero(expr->srcmemidx, expr->destmemidx,
+ NextChar::Space);
+ writer_->WriteNewline(NO_FORCE_NEWLINE);
return Result::Ok;
}
@@ -740,23 +784,31 @@ Result WatWriter::ExprVisitorDelegate::OnDataDropExpr(DataDropExpr* expr) {
}
Result WatWriter::ExprVisitorDelegate::OnMemoryFillExpr(MemoryFillExpr* expr) {
- writer_->WritePutsNewline(Opcode::MemoryFill_Opcode.GetName());
+ writer_->WritePutsSpace(Opcode::MemoryFill_Opcode.GetName());
+ writer_->WriteMemoryVarUnlessZero(expr->memidx, NextChar::Space);
+ writer_->WriteNewline(NO_FORCE_NEWLINE);
return Result::Ok;
}
Result WatWriter::ExprVisitorDelegate::OnMemoryGrowExpr(MemoryGrowExpr* expr) {
- writer_->WritePutsNewline(Opcode::MemoryGrow_Opcode.GetName());
+ writer_->WritePutsSpace(Opcode::MemoryGrow_Opcode.GetName());
+ writer_->WriteMemoryVarUnlessZero(expr->memidx, NextChar::Space);
+ writer_->WriteNewline(NO_FORCE_NEWLINE);
return Result::Ok;
}
Result WatWriter::ExprVisitorDelegate::OnMemorySizeExpr(MemorySizeExpr* expr) {
- writer_->WritePutsNewline(Opcode::MemorySize_Opcode.GetName());
+ writer_->WritePutsSpace(Opcode::MemorySize_Opcode.GetName());
+ writer_->WriteMemoryVarUnlessZero(expr->memidx, NextChar::Space);
+ writer_->WriteNewline(NO_FORCE_NEWLINE);
return Result::Ok;
}
Result WatWriter::ExprVisitorDelegate::OnMemoryInitExpr(MemoryInitExpr* expr) {
writer_->WritePutsSpace(Opcode::MemoryInit_Opcode.GetName());
- writer_->WriteVar(expr->var, NextChar::Newline);
+ writer_->WriteVar(expr->var, NextChar::Space);
+ writer_->WriteMemoryVarUnlessZero(expr->memidx, NextChar::Space);
+ writer_->WriteNewline(NO_FORCE_NEWLINE);
return Result::Ok;
}
@@ -865,7 +917,7 @@ Result WatWriter::ExprVisitorDelegate::OnSelectExpr(SelectExpr* expr) {
}
Result WatWriter::ExprVisitorDelegate::OnStoreExpr(StoreExpr* expr) {
- writer_->WriteLoadStoreExpr<StoreExpr>(expr);
+ writer_->WriteMemoryLoadStoreExpr<StoreExpr>(expr);
return Result::Ok;
}
@@ -1423,6 +1475,7 @@ void WatWriter::WriteDataSegment(const DataSegment& segment) {
WriteOpenSpace("data");
WriteNameOrIndex(segment.name, data_segment_index_, NextChar::Space);
if (segment.kind != SegmentKind::Passive) {
+ WriteMemoryVarUnlessZero(segment.memory_var, NextChar::Space);
WriteInitExpr(segment.offset);
}
WriteQuotedData(segment.data.data(), segment.data.size());