summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binary-reader-ir.cc16
-rw-r--r--src/binary-reader-logging.cc11
-rw-r--r--src/binary-reader-objdump.cc20
-rw-r--r--src/binary-reader.cc33
-rw-r--r--src/binary-writer.cc23
-rw-r--r--src/interp/binary-reader-interp.cc22
-rw-r--r--src/interp/interp-wasm-c-api.cc5
-rw-r--r--src/interp/interp.cc10
-rw-r--r--src/lexer-keywords.txt1
-rw-r--r--src/prebuilt/lexer-keywords.cc122
-rw-r--r--src/shared-validator.cc18
-rw-r--r--src/test-interp.cc5
-rw-r--r--src/tools/spectest-interp.cc3
-rw-r--r--src/validator.cc6
-rw-r--r--src/wast-parser.cc53
-rw-r--r--src/wat-writer.cc5
16 files changed, 246 insertions, 107 deletions
diff --git a/src/binary-reader-ir.cc b/src/binary-reader-ir.cc
index 2ab3b098..04b2e90b 100644
--- a/src/binary-reader-ir.cc
+++ b/src/binary-reader-ir.cc
@@ -126,7 +126,8 @@ class BinaryReaderIR : public BinaryReaderNop {
std::string_view module_name,
std::string_view field_name,
Index memory_index,
- const Limits* page_limits) override;
+ const Limits* page_limits,
+ uint32_t page_size) override;
Result OnImportGlobal(Index import_index,
std::string_view module_name,
std::string_view field_name,
@@ -148,7 +149,9 @@ class BinaryReaderIR : public BinaryReaderNop {
const Limits* elem_limits) override;
Result OnMemoryCount(Index count) override;
- Result OnMemory(Index index, const Limits* limits) override;
+ Result OnMemory(Index index,
+ const Limits* limits,
+ uint32_t page_size) override;
Result OnGlobalCount(Index count) override;
Result BeginGlobal(Index index, Type type, bool mutable_) override;
@@ -620,11 +623,13 @@ Result BinaryReaderIR::OnImportMemory(Index import_index,
std::string_view module_name,
std::string_view field_name,
Index memory_index,
- const Limits* page_limits) {
+ const Limits* page_limits,
+ uint32_t page_size) {
auto import = std::make_unique<MemoryImport>();
import->module_name = module_name;
import->field_name = field_name;
import->memory.page_limits = *page_limits;
+ import->memory.page_size = page_size;
if (import->memory.page_limits.is_shared) {
module_->features_used.threads = true;
}
@@ -707,10 +712,13 @@ Result BinaryReaderIR::OnMemoryCount(Index count) {
return Result::Ok;
}
-Result BinaryReaderIR::OnMemory(Index index, const Limits* page_limits) {
+Result BinaryReaderIR::OnMemory(Index index,
+ const Limits* page_limits,
+ uint32_t page_size) {
auto field = std::make_unique<MemoryModuleField>(GetLocation());
Memory& memory = field->memory;
memory.page_limits = *page_limits;
+ memory.page_size = page_size;
if (memory.page_limits.is_shared) {
module_->features_used.threads = true;
}
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc
index ea427391..0c3fcda6 100644
--- a/src/binary-reader-logging.cc
+++ b/src/binary-reader-logging.cc
@@ -217,14 +217,15 @@ Result BinaryReaderLogging::OnImportMemory(Index import_index,
std::string_view module_name,
std::string_view field_name,
Index memory_index,
- const Limits* page_limits) {
+ const Limits* page_limits,
+ uint32_t page_size) {
char buf[100];
SPrintLimits(buf, sizeof(buf), page_limits);
LOGF("OnImportMemory(import_index: %" PRIindex ", memory_index: %" PRIindex
", %s)\n",
import_index, memory_index, buf);
return reader_->OnImportMemory(import_index, module_name, field_name,
- memory_index, page_limits);
+ memory_index, page_limits, page_size);
}
Result BinaryReaderLogging::OnImportGlobal(Index import_index,
@@ -264,11 +265,13 @@ Result BinaryReaderLogging::OnTable(Index index,
return reader_->OnTable(index, elem_type, elem_limits);
}
-Result BinaryReaderLogging::OnMemory(Index index, const Limits* page_limits) {
+Result BinaryReaderLogging::OnMemory(Index index,
+ const Limits* page_limits,
+ uint32_t page_size) {
char buf[100];
SPrintLimits(buf, sizeof(buf), page_limits);
LOGF("OnMemory(index: %" PRIindex ", %s)\n", index, buf);
- return reader_->OnMemory(index, page_limits);
+ return reader_->OnMemory(index, page_limits, page_size);
}
Result BinaryReaderLogging::BeginGlobal(Index index, Type type, bool mutable_) {
diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc
index ff9afbc6..52e6d27a 100644
--- a/src/binary-reader-objdump.cc
+++ b/src/binary-reader-objdump.cc
@@ -1059,7 +1059,8 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
std::string_view module_name,
std::string_view field_name,
Index memory_index,
- const Limits* page_limits) override;
+ const Limits* page_limits,
+ uint32_t page_size) override;
Result OnImportGlobal(Index import_index,
std::string_view module_name,
std::string_view field_name,
@@ -1081,7 +1082,9 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
const Limits* elem_limits) override;
Result OnMemoryCount(Index count) override;
- Result OnMemory(Index index, const Limits* limits) override;
+ Result OnMemory(Index index,
+ const Limits* limits,
+ uint32_t page_size) override;
Result OnGlobalCount(Index count) override;
Result BeginGlobal(Index index, Type type, bool mutable_) override;
@@ -1563,7 +1566,8 @@ Result BinaryReaderObjdump::OnImportMemory(Index import_index,
std::string_view module_name,
std::string_view field_name,
Index memory_index,
- const Limits* page_limits) {
+ const Limits* page_limits,
+ uint32_t page_size) {
PrintDetails(" - memory[%" PRIindex "] pages: initial=%" PRId64, memory_index,
page_limits->initial);
if (page_limits->has_max) {
@@ -1575,6 +1579,9 @@ Result BinaryReaderObjdump::OnImportMemory(Index import_index,
if (page_limits->is_64) {
PrintDetails(" i64");
}
+ if (page_size != WABT_DEFAULT_PAGE_SIZE) {
+ PrintDetails(" (pagesize %u)", page_size);
+ }
PrintDetails(" <- " PRIstringview "." PRIstringview "\n",
WABT_PRINTF_STRING_VIEW_ARG(module_name),
WABT_PRINTF_STRING_VIEW_ARG(field_name));
@@ -1615,7 +1622,9 @@ Result BinaryReaderObjdump::OnMemoryCount(Index count) {
return OnCount(count);
}
-Result BinaryReaderObjdump::OnMemory(Index index, const Limits* page_limits) {
+Result BinaryReaderObjdump::OnMemory(Index index,
+ const Limits* page_limits,
+ uint32_t page_size) {
PrintDetails(" - memory[%" PRIindex "] pages: initial=%" PRId64, index,
page_limits->initial);
if (page_limits->has_max) {
@@ -1627,6 +1636,9 @@ Result BinaryReaderObjdump::OnMemory(Index index, const Limits* page_limits) {
if (page_limits->is_64) {
PrintDetails(" i64");
}
+ if (page_size != WABT_DEFAULT_PAGE_SIZE) {
+ PrintDetails(" (pagesize %u)", page_size);
+ }
PrintDetails("\n");
return Result::Ok;
}
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index 33801a7d..18b57e05 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -146,7 +146,8 @@ class BinaryReader {
[[nodiscard]] Result ReadInitExpr(Index index);
[[nodiscard]] Result ReadTable(Type* out_elem_type, Limits* out_elem_limits);
- [[nodiscard]] Result ReadMemory(Limits* out_page_limits);
+ [[nodiscard]] Result ReadMemory(Limits* out_page_limits,
+ uint32_t* out_page_size);
[[nodiscard]] Result ReadGlobalHeader(Type* out_type, bool* out_mutable);
[[nodiscard]] Result ReadTagType(Index* out_sig_index);
[[nodiscard]] Result ReadAddress(Address* out_value,
@@ -600,7 +601,7 @@ Result BinaryReader::ReadTable(Type* out_elem_type, Limits* out_elem_limits) {
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;
+ const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_TABLE_FLAGS;
ERROR_IF(is_shared, "tables may not be shared");
ERROR_IF(is_64 && !options_.features.memory64_enabled(),
"memory64 not allowed");
@@ -617,7 +618,8 @@ Result BinaryReader::ReadTable(Type* out_elem_type, Limits* out_elem_limits) {
return Result::Ok;
}
-Result BinaryReader::ReadMemory(Limits* out_page_limits) {
+Result BinaryReader::ReadMemory(Limits* out_page_limits,
+ uint32_t* out_page_size) {
uint8_t flags;
uint64_t initial;
uint64_t max = 0;
@@ -625,12 +627,17 @@ Result BinaryReader::ReadMemory(Limits* out_page_limits) {
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;
+ bool has_custom_page_size =
+ flags & WABT_BINARY_LIMITS_HAS_CUSTOM_PAGE_SIZE_FLAG;
+ const uint8_t unknown_flags = flags & ~WABT_BINARY_LIMITS_ALL_MEMORY_FLAGS;
ERROR_UNLESS(unknown_flags == 0, "malformed memory limits flag: %d", flags);
ERROR_IF(is_shared && !options_.features.threads_enabled(),
"memory may not be shared: threads not allowed");
ERROR_IF(is_64 && !options_.features.memory64_enabled(),
"memory64 not allowed");
+ ERROR_IF(
+ has_custom_page_size && !options_.features.custom_page_sizes_enabled(),
+ "custom page sizes not allowed");
if (options_.features.memory64_enabled()) {
CHECK_RESULT(ReadU64Leb128(&initial, "memory initial page count"));
if (has_max) {
@@ -646,6 +653,14 @@ Result BinaryReader::ReadMemory(Limits* out_page_limits) {
max = max32;
}
}
+ if (has_custom_page_size) {
+ uint32_t page_size_log2;
+ CHECK_RESULT(ReadU32Leb128(&page_size_log2, "memory page size"));
+ ERROR_IF(page_size_log2 > 16, "malformed memory page size");
+ *out_page_size = 1 << page_size_log2;
+ } else {
+ *out_page_size = WABT_DEFAULT_PAGE_SIZE;
+ }
out_page_limits->has_max = has_max;
out_page_limits->is_shared = is_shared;
@@ -2586,9 +2601,10 @@ Result BinaryReader::ReadImportSection(Offset section_size) {
case ExternalKind::Memory: {
Limits page_limits;
- CHECK_RESULT(ReadMemory(&page_limits));
+ uint32_t page_size;
+ CHECK_RESULT(ReadMemory(&page_limits, &page_size));
CALLBACK(OnImportMemory, i, module_name, field_name,
- num_memory_imports_, &page_limits);
+ num_memory_imports_, &page_limits, page_size);
num_memory_imports_++;
break;
}
@@ -2663,8 +2679,9 @@ Result BinaryReader::ReadMemorySection(Offset section_size) {
for (Index i = 0; i < num_memories; ++i) {
Index memory_index = num_memory_imports_ + i;
Limits page_limits;
- CHECK_RESULT(ReadMemory(&page_limits));
- CALLBACK(OnMemory, memory_index, &page_limits);
+ uint32_t page_size;
+ CHECK_RESULT(ReadMemory(&page_limits, &page_size));
+ CALLBACK(OnMemory, memory_index, &page_limits, page_size);
}
CALLBACK0(EndMemorySection);
return Result::Ok;
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index a94eb147..60863d62 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -64,11 +64,18 @@ void WriteType(Stream* stream, Type type, const char* desc) {
}
}
-void WriteLimits(Stream* stream, const Limits* limits) {
+void WriteLimitsFlags(Stream* stream, uint32_t flags) {
+ WriteU32Leb128(stream, flags, "limits: flags");
+}
+
+uint32_t ComputeLimitsFlags(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");
+ return flags;
+}
+
+void WriteLimitsData(Stream* stream, const Limits* limits) {
if (limits->is_64) {
WriteU64Leb128(stream, limits->initial, "limits: initial");
if (limits->has_max) {
@@ -1157,11 +1164,19 @@ void BinaryWriter::WriteFunc(const Func* func) {
void BinaryWriter::WriteTable(const Table* table) {
WriteType(stream_, table->elem_type);
- WriteLimits(stream_, &table->elem_limits);
+ WriteLimitsFlags(stream_, ComputeLimitsFlags(&table->elem_limits));
+ WriteLimitsData(stream_, &table->elem_limits);
}
void BinaryWriter::WriteMemory(const Memory* memory) {
- WriteLimits(stream_, &memory->page_limits);
+ uint32_t flags = ComputeLimitsFlags(&memory->page_limits);
+ const bool custom_page_size = memory->page_size != WABT_DEFAULT_PAGE_SIZE;
+ flags |= custom_page_size ? WABT_BINARY_LIMITS_HAS_CUSTOM_PAGE_SIZE_FLAG : 0;
+ WriteLimitsFlags(stream_, flags);
+ WriteLimitsData(stream_, &memory->page_limits);
+ if (custom_page_size) {
+ WriteU32Leb128(stream_, log2_u32(memory->page_size), "memory page size");
+ }
}
void BinaryWriter::WriteGlobalHeader(const Global* global) {
diff --git a/src/interp/binary-reader-interp.cc b/src/interp/binary-reader-interp.cc
index dc7ec410..1d3daf8e 100644
--- a/src/interp/binary-reader-interp.cc
+++ b/src/interp/binary-reader-interp.cc
@@ -105,7 +105,8 @@ class BinaryReaderInterp : public BinaryReaderNop {
std::string_view module_name,
std::string_view field_name,
Index memory_index,
- const Limits* page_limits) override;
+ const Limits* page_limits,
+ uint32_t page_size) override;
Result OnImportGlobal(Index import_index,
std::string_view module_name,
std::string_view field_name,
@@ -127,7 +128,9 @@ class BinaryReaderInterp : public BinaryReaderNop {
const Limits* elem_limits) override;
Result OnMemoryCount(Index count) override;
- Result OnMemory(Index index, const Limits* limits) override;
+ Result OnMemory(Index index,
+ const Limits* limits,
+ uint32_t page_size) override;
Result OnGlobalCount(Index count) override;
Result BeginGlobal(Index index, Type type, bool mutable_) override;
@@ -537,9 +540,10 @@ Result BinaryReaderInterp::OnImportMemory(Index import_index,
std::string_view module_name,
std::string_view field_name,
Index memory_index,
- const Limits* page_limits) {
- CHECK_RESULT(validator_.OnMemory(GetLocation(), *page_limits));
- MemoryType memory_type{*page_limits};
+ const Limits* page_limits,
+ uint32_t page_size) {
+ CHECK_RESULT(validator_.OnMemory(GetLocation(), *page_limits, page_size));
+ MemoryType memory_type{*page_limits, page_size};
module_.imports.push_back(ImportDesc{ImportType(
std::string(module_name), std::string(field_name), memory_type.Clone())});
memory_types_.push_back(memory_type);
@@ -608,9 +612,11 @@ Result BinaryReaderInterp::OnMemoryCount(Index count) {
return Result::Ok;
}
-Result BinaryReaderInterp::OnMemory(Index index, const Limits* limits) {
- CHECK_RESULT(validator_.OnMemory(GetLocation(), *limits));
- MemoryType memory_type{*limits};
+Result BinaryReaderInterp::OnMemory(Index index,
+ const Limits* limits,
+ uint32_t page_size) {
+ CHECK_RESULT(validator_.OnMemory(GetLocation(), *limits, page_size));
+ MemoryType memory_type{*limits, page_size};
module_.memories.push_back(MemoryDesc{memory_type});
memory_types_.push_back(memory_type);
return Result::Ok;
diff --git a/src/interp/interp-wasm-c-api.cc b/src/interp/interp-wasm-c-api.cc
index cfa8a897..bb4598a4 100644
--- a/src/interp/interp-wasm-c-api.cc
+++ b/src/interp/interp-wasm-c-api.cc
@@ -160,7 +160,10 @@ struct wasm_tabletype_t : wasm_externtype_t {
struct wasm_memorytype_t : wasm_externtype_t {
wasm_memorytype_t(const wasm_limits_t* limits)
- : wasm_externtype_t{std::make_unique<MemoryType>(ToWabtLimits(*limits))},
+ : wasm_externtype_t{std::make_unique<MemoryType>(
+ ToWabtLimits(*limits),
+ WABT_DEFAULT_PAGE_SIZE)}, // wasm-c-api doesn't support
+ // custom-page-sizes yet
limits{*limits} {}
wasm_memorytype_t(MemoryType mt)
diff --git a/src/interp/interp.cc b/src/interp/interp.cc
index a3dd9b4a..f93fa5a6 100644
--- a/src/interp/interp.cc
+++ b/src/interp/interp.cc
@@ -136,6 +136,12 @@ std::unique_ptr<ExternType> MemoryType::Clone() const {
Result Match(const MemoryType& expected,
const MemoryType& actual,
std::string* out_msg) {
+ if (expected.page_size != actual.page_size) {
+ *out_msg = StringPrintf(
+ "page_size mismatch in imported memory, expected %u but got %u.",
+ expected.page_size, actual.page_size);
+ return Result::Error;
+ }
return Match(expected.limits, actual.limits, out_msg);
}
@@ -576,7 +582,7 @@ Result Table::Copy(Store& store,
//// Memory ////
Memory::Memory(class Store&, MemoryType type)
: Extern(skind), type_(type), pages_(type.limits.initial) {
- data_.resize(pages_ * WABT_PAGE_SIZE);
+ data_.resize(pages_ * type_.page_size);
}
void Memory::Mark(class Store&) {}
@@ -597,7 +603,7 @@ Result Memory::Grow(u64 count) {
auto old_size = data_.size();
#endif
pages_ = new_pages;
- data_.resize(new_pages * WABT_PAGE_SIZE);
+ data_.resize(new_pages * type_.page_size);
#if WABT_BIG_ENDIAN
std::move_backward(data_.begin(), data_.begin() + old_size, data_.end());
std::fill(data_.begin(), data_.end() - old_size, 0);
diff --git a/src/lexer-keywords.txt b/src/lexer-keywords.txt
index e4fd37d3..1c72983b 100644
--- a/src/lexer-keywords.txt
+++ b/src/lexer-keywords.txt
@@ -556,6 +556,7 @@ nan:canonical, TokenType::NanCanonical
nop, TokenType::Nop, Opcode::Nop
offset, TokenType::Offset
output, TokenType::Output
+pagesize, TokenType::PageSize
param, TokenType::Param
ref, TokenType::Ref
quote, TokenType::Quote
diff --git a/src/prebuilt/lexer-keywords.cc b/src/prebuilt/lexer-keywords.cc
index 32b6951a..f04fc537 100644
--- a/src/prebuilt/lexer-keywords.cc
+++ b/src/prebuilt/lexer-keywords.cc
@@ -158,7 +158,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{
enum
{
- TOTAL_KEYWORDS = 596,
+ TOTAL_KEYWORDS = 597,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 35,
MIN_HASH_VALUE = 15,
@@ -224,7 +224,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"f32x4.lt", TokenType::Compare, Opcode::F32X4Lt},
#line 340 "src/lexer-keywords.txt"
{"i32x4.lt_u", TokenType::Compare, Opcode::I32X4LtU},
-#line 567 "src/lexer-keywords.txt"
+#line 568 "src/lexer-keywords.txt"
{"result", TokenType::Result},
#line 329 "src/lexer-keywords.txt"
{"i32x4.gt_s", TokenType::Compare, Opcode::I32X4GtS},
@@ -258,10 +258,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""},
#line 107 "src/lexer-keywords.txt"
{"f32x4.ne", TokenType::Compare, Opcode::F32X4Ne},
-#line 565 "src/lexer-keywords.txt"
+#line 566 "src/lexer-keywords.txt"
{"ref.null", TokenType::RefNull, Opcode::RefNull},
{""},
-#line 583 "src/lexer-keywords.txt"
+#line 584 "src/lexer-keywords.txt"
{"table", TokenType::Table},
#line 347 "src/lexer-keywords.txt"
{"i32x4.neg", TokenType::Unary, Opcode::I32X4Neg},
@@ -281,15 +281,15 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""}, {""}, {""}, {""},
#line 105 "src/lexer-keywords.txt"
{"f32x4.nearest", TokenType::Unary, Opcode::F32X4Nearest},
-#line 571 "src/lexer-keywords.txt"
+#line 572 "src/lexer-keywords.txt"
{"return", TokenType::Return, Opcode::Return},
#line 91 "src/lexer-keywords.txt"
{"f32x4.ceil", TokenType::Unary, Opcode::F32X4Ceil},
{""}, {""}, {""},
-#line 578 "src/lexer-keywords.txt"
+#line 579 "src/lexer-keywords.txt"
{"table.get", TokenType::TableGet, Opcode::TableGet},
{""},
-#line 581 "src/lexer-keywords.txt"
+#line 582 "src/lexer-keywords.txt"
{"table.set", TokenType::TableSet, Opcode::TableSet},
{""},
#line 141 "src/lexer-keywords.txt"
@@ -297,7 +297,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 80 "src/lexer-keywords.txt"
{"f32.nearest", TokenType::Unary, Opcode::F32Nearest},
{""},
-#line 575 "src/lexer-keywords.txt"
+#line 576 "src/lexer-keywords.txt"
{"struct", Type::Struct, TokenType::Struct},
#line 147 "src/lexer-keywords.txt"
{"f64.store", TokenType::Store, Opcode::F64Store},
@@ -348,7 +348,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 346 "src/lexer-keywords.txt"
{"i32x4.mul", TokenType::Binary, Opcode::I32X4Mul},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 562 "src/lexer-keywords.txt"
+#line 563 "src/lexer-keywords.txt"
{"ref.extern", TokenType::RefExtern},
{""}, {""},
#line 451 "src/lexer-keywords.txt"
@@ -410,7 +410,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 349 "src/lexer-keywords.txt"
{"i32x4.relaxed_laneselect", TokenType::Ternary, Opcode::I32X4RelaxedLaneSelect},
{""}, {""}, {""}, {""},
-#line 572 "src/lexer-keywords.txt"
+#line 573 "src/lexer-keywords.txt"
{"select", TokenType::Select, Opcode::Select},
{""},
#line 373 "src/lexer-keywords.txt"
@@ -519,7 +519,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"i64.trunc_f32_s", TokenType::Convert, Opcode::I64TruncF32S},
#line 310 "src/lexer-keywords.txt"
{"i32.trunc_f32_s", TokenType::Convert, Opcode::I32TruncF32S},
-#line 566 "src/lexer-keywords.txt"
+#line 567 "src/lexer-keywords.txt"
{"register", TokenType::Register},
{""},
#line 429 "src/lexer-keywords.txt"
@@ -536,7 +536,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 61 "src/lexer-keywords.txt"
{"f32.ceil", TokenType::Unary, Opcode::F32Ceil},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 582 "src/lexer-keywords.txt"
+#line 583 "src/lexer-keywords.txt"
{"table.size", TokenType::TableSize, Opcode::TableSize},
#line 409 "src/lexer-keywords.txt"
{"i64.atomic.store", TokenType::AtomicStore, Opcode::I64AtomicStore},
@@ -547,7 +547,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 265 "src/lexer-keywords.txt"
{"i32.atomic.rmw.or", TokenType::AtomicRmw, Opcode::I32AtomicRmwOr},
{""}, {""}, {""}, {""}, {""},
-#line 570 "src/lexer-keywords.txt"
+#line 571 "src/lexer-keywords.txt"
{"return_call", TokenType::ReturnCall, Opcode::ReturnCall},
{""}, {""}, {""}, {""}, {""}, {""},
#line 389 "src/lexer-keywords.txt"
@@ -583,9 +583,9 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 88 "src/lexer-keywords.txt"
{"f32", Type::F32},
{""},
-#line 580 "src/lexer-keywords.txt"
+#line 581 "src/lexer-keywords.txt"
{"table.init", TokenType::TableInit, Opcode::TableInit},
-#line 586 "src/lexer-keywords.txt"
+#line 587 "src/lexer-keywords.txt"
{"try", TokenType::Try, Opcode::Try},
{""}, {""},
#line 318 "src/lexer-keywords.txt"
@@ -730,7 +730,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""}, {""},
#line 353 "src/lexer-keywords.txt"
{"i32x4.shr_u", TokenType::Binary, Opcode::I32X4ShrU},
-#line 564 "src/lexer-keywords.txt"
+#line 565 "src/lexer-keywords.txt"
{"ref.is_null", TokenType::RefIsNull, Opcode::RefIsNull},
#line 352 "src/lexer-keywords.txt"
{"i32x4.shr_s", TokenType::Binary, Opcode::I32X4ShrS},
@@ -756,10 +756,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 467 "src/lexer-keywords.txt"
{"i64x2.mul", TokenType::Binary, Opcode::I64X2Mul},
{""}, {""}, {""}, {""}, {""}, {""},
-#line 561 "src/lexer-keywords.txt"
+#line 562 "src/lexer-keywords.txt"
{"quote", TokenType::Quote},
{""}, {""}, {""}, {""},
-#line 600 "src/lexer-keywords.txt"
+#line 601 "src/lexer-keywords.txt"
{"v128", Type::V128},
{""},
#line 536 "src/lexer-keywords.txt"
@@ -832,7 +832,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"i32x4.relaxed_trunc_f32x4_s", TokenType::Unary, Opcode::I32X4RelaxedTruncF32X4S},
#line 420 "src/lexer-keywords.txt"
{"i64.extend_i32_s", TokenType::Convert, Opcode::I64ExtendI32S},
-#line 595 "src/lexer-keywords.txt"
+#line 596 "src/lexer-keywords.txt"
{"v128.or", TokenType::Binary, Opcode::V128Or},
{""},
#line 555 "src/lexer-keywords.txt"
@@ -855,7 +855,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""},
#line 171 "src/lexer-keywords.txt"
{"f64x2.relaxed_max", TokenType::Binary, Opcode::F64X2RelaxedMax},
-#line 599 "src/lexer-keywords.txt"
+#line 600 "src/lexer-keywords.txt"
{"v128.store", TokenType::Store, Opcode::V128Store},
{""},
#line 395 "src/lexer-keywords.txt"
@@ -867,7 +867,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""},
#line 203 "src/lexer-keywords.txt"
{"i16x8.ge_u", TokenType::Compare, Opcode::I16X8GeU},
-#line 601 "src/lexer-keywords.txt"
+#line 602 "src/lexer-keywords.txt"
{"v128.xor", TokenType::Binary, Opcode::V128Xor},
#line 207 "src/lexer-keywords.txt"
{"i16x8.le_u", TokenType::Compare, Opcode::I16X8LeU},
@@ -895,24 +895,24 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 523 "src/lexer-keywords.txt"
{"i8x16.relaxed_laneselect", TokenType::Ternary, Opcode::I8X16RelaxedLaneSelect},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 587 "src/lexer-keywords.txt"
+#line 588 "src/lexer-keywords.txt"
{"type", TokenType::Type},
#line 404 "src/lexer-keywords.txt"
{"i64.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I64AtomicRmwXchg},
#line 267 "src/lexer-keywords.txt"
{"i32.atomic.rmw.xchg", TokenType::AtomicRmw, Opcode::I32AtomicRmwXchg},
{""},
-#line 594 "src/lexer-keywords.txt"
+#line 595 "src/lexer-keywords.txt"
{"v128.not", TokenType::Unary, Opcode::V128Not},
{""}, {""},
-#line 613 "src/lexer-keywords.txt"
+#line 614 "src/lexer-keywords.txt"
{"v128.store64_lane", TokenType::SimdStoreLane, Opcode::V128Store64Lane},
#line 219 "src/lexer-keywords.txt"
{"i16x8.neg", TokenType::Unary, Opcode::I16X8Neg},
{""},
#line 221 "src/lexer-keywords.txt"
{"i16x8.ne", TokenType::Compare, Opcode::I16X8Ne},
-#line 606 "src/lexer-keywords.txt"
+#line 607 "src/lexer-keywords.txt"
{"v128.load8_lane", TokenType::SimdLoadLane, Opcode::V128Load8Lane},
#line 466 "src/lexer-keywords.txt"
{"v128.load32x2_u", TokenType::Load, Opcode::V128Load32X2U},
@@ -934,9 +934,9 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 535 "src/lexer-keywords.txt"
{"input", TokenType::Input},
{""}, {""},
-#line 593 "src/lexer-keywords.txt"
+#line 594 "src/lexer-keywords.txt"
{"v128.load", TokenType::Load, Opcode::V128Load},
-#line 605 "src/lexer-keywords.txt"
+#line 606 "src/lexer-keywords.txt"
{"v128.load8_splat", TokenType::Load, Opcode::V128Load8Splat},
{""},
#line 534 "src/lexer-keywords.txt"
@@ -956,7 +956,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""}, {""},
#line 116 "src/lexer-keywords.txt"
{"f32x4.sqrt", TokenType::Unary, Opcode::F32X4Sqrt},
-#line 569 "src/lexer-keywords.txt"
+#line 570 "src/lexer-keywords.txt"
{"return_call_indirect", TokenType::ReturnCallIndirect, Opcode::ReturnCallIndirect},
{""}, {""}, {""}, {""}, {""}, {""},
#line 397 "src/lexer-keywords.txt"
@@ -972,7 +972,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 108 "src/lexer-keywords.txt"
{"f32x4.pmax", TokenType::Binary, Opcode::F32X4PMax},
{""}, {""}, {""}, {""},
-#line 592 "src/lexer-keywords.txt"
+#line 593 "src/lexer-keywords.txt"
{"v128.const", TokenType::Const, Opcode::V128Const},
#line 173 "src/lexer-keywords.txt"
{"f64x2.relaxed_nmadd", TokenType::Ternary, Opcode::F64X2RelaxedNmadd},
@@ -980,11 +980,11 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 525 "src/lexer-keywords.txt"
{"i8x16.shl", TokenType::Binary, Opcode::I8X16Shl},
{""},
-#line 590 "src/lexer-keywords.txt"
+#line 591 "src/lexer-keywords.txt"
{"v128.and", TokenType::Binary, Opcode::V128And},
#line 533 "src/lexer-keywords.txt"
{"if", TokenType::If, Opcode::If},
-#line 560 "src/lexer-keywords.txt"
+#line 561 "src/lexer-keywords.txt"
{"ref", TokenType::Ref},
{""}, {""}, {""},
#line 551 "src/lexer-keywords.txt"
@@ -995,7 +995,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 216 "src/lexer-keywords.txt"
{"i16x8.mul", TokenType::Binary, Opcode::I16X8Mul},
{""}, {""}, {""}, {""},
-#line 589 "src/lexer-keywords.txt"
+#line 590 "src/lexer-keywords.txt"
{"v128.andnot", TokenType::Binary, Opcode::V128Andnot},
#line 51 "src/lexer-keywords.txt"
{"else", TokenType::Else, Opcode::Else},
@@ -1013,10 +1013,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 224 "src/lexer-keywords.txt"
{"i16x8.replace_lane", TokenType::SimdLaneOp, Opcode::I16X8ReplaceLane},
{""}, {""}, {""}, {""}, {""}, {""},
-#line 584 "src/lexer-keywords.txt"
+#line 585 "src/lexer-keywords.txt"
{"then", TokenType::Then},
{""},
-#line 611 "src/lexer-keywords.txt"
+#line 612 "src/lexer-keywords.txt"
{"v128.store16_lane", TokenType::SimdStoreLane, Opcode::V128Store16Lane},
{""}, {""}, {""}, {""},
#line 163 "src/lexer-keywords.txt"
@@ -1087,7 +1087,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 230 "src/lexer-keywords.txt"
{"i16x8.sub_sat_u", TokenType::Binary, Opcode::I16X8SubSatU},
{""},
-#line 576 "src/lexer-keywords.txt"
+#line 577 "src/lexer-keywords.txt"
{"table.copy", TokenType::TableCopy, Opcode::TableCopy},
{""},
#line 229 "src/lexer-keywords.txt"
@@ -1096,7 +1096,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 522 "src/lexer-keywords.txt"
{"i8x16.relaxed_swizzle", TokenType::Binary, Opcode::I8X16RelaxedSwizzle},
{""}, {""},
-#line 603 "src/lexer-keywords.txt"
+#line 604 "src/lexer-keywords.txt"
{"v128.load32_splat", TokenType::Load, Opcode::V128Load32Splat},
{""}, {""}, {""}, {""}, {""},
#line 486 "src/lexer-keywords.txt"
@@ -1104,13 +1104,13 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{""},
#line 485 "src/lexer-keywords.txt"
{"i64x2.shr_s", TokenType::Binary, Opcode::I64X2ShrS},
-#line 610 "src/lexer-keywords.txt"
+#line 611 "src/lexer-keywords.txt"
{"v128.store8_lane", TokenType::SimdStoreLane, Opcode::V128Store8Lane},
{""},
#line 183 "src/lexer-keywords.txt"
{"field", TokenType::Field},
{""},
-#line 608 "src/lexer-keywords.txt"
+#line 609 "src/lexer-keywords.txt"
{"v128.load32_lane", TokenType::SimdLoadLane, Opcode::V128Load32Lane},
{""}, {""},
#line 21 "src/lexer-keywords.txt"
@@ -1122,7 +1122,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"f64.floor", TokenType::Unary, Opcode::F64Floor},
#line 71 "src/lexer-keywords.txt"
{"f32.floor", TokenType::Unary, Opcode::F32Floor},
-#line 559 "src/lexer-keywords.txt"
+#line 560 "src/lexer-keywords.txt"
{"param", TokenType::Param},
{""},
#line 549 "src/lexer-keywords.txt"
@@ -1131,19 +1131,19 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 117 "src/lexer-keywords.txt"
{"f32x4.sub", TokenType::Binary, Opcode::F32X4Sub},
{""}, {""}, {""}, {""},
-#line 597 "src/lexer-keywords.txt"
+#line 598 "src/lexer-keywords.txt"
{"v128.load32_zero", TokenType::Load, Opcode::V128Load32Zero},
#line 355 "src/lexer-keywords.txt"
{"i32x4.sub", TokenType::Binary, Opcode::I32X4Sub},
{""}, {""}, {""},
-#line 563 "src/lexer-keywords.txt"
+#line 564 "src/lexer-keywords.txt"
{"ref.func", TokenType::RefFunc, Opcode::RefFunc},
{""},
#line 121 "src/lexer-keywords.txt"
{"f64.abs", TokenType::Unary, Opcode::F64Abs},
#line 59 "src/lexer-keywords.txt"
{"f32.abs", TokenType::Unary, Opcode::F32Abs},
-#line 574 "src/lexer-keywords.txt"
+#line 575 "src/lexer-keywords.txt"
{"start", TokenType::Start},
#line 449 "src/lexer-keywords.txt"
{"i64.store16", TokenType::Store, Opcode::I64Store16},
@@ -1161,7 +1161,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 526 "src/lexer-keywords.txt"
{"i8x16.shr_s", TokenType::Binary, Opcode::I8X16ShrS},
{""}, {""}, {""},
-#line 596 "src/lexer-keywords.txt"
+#line 597 "src/lexer-keywords.txt"
{"v128.any_true", TokenType::Unary, Opcode::V128AnyTrue},
{""}, {""}, {""}, {""}, {""}, {""},
#line 193 "src/lexer-keywords.txt"
@@ -1182,7 +1182,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
{"i16x8.max_s", TokenType::Binary, Opcode::I16X8MaxS},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""},
-#line 604 "src/lexer-keywords.txt"
+#line 605 "src/lexer-keywords.txt"
{"v128.load64_splat", TokenType::Load, Opcode::V128Load64Splat},
{""}, {""}, {""},
#line 375 "src/lexer-keywords.txt"
@@ -1190,7 +1190,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 34 "src/lexer-keywords.txt"
{"br_table", TokenType::BrTable, Opcode::BrTable},
{""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 609 "src/lexer-keywords.txt"
+#line 610 "src/lexer-keywords.txt"
{"v128.load64_lane", TokenType::SimdLoadLane, Opcode::V128Load64Lane},
#line 94 "src/lexer-keywords.txt"
{"f32x4.div", TokenType::Binary, Opcode::F32X4Div},
@@ -1217,10 +1217,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 528 "src/lexer-keywords.txt"
{"i8x16.splat", TokenType::Unary, Opcode::I8X16Splat},
{""}, {""},
-#line 598 "src/lexer-keywords.txt"
+#line 599 "src/lexer-keywords.txt"
{"v128.load64_zero", TokenType::Load, Opcode::V128Load64Zero},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 585 "src/lexer-keywords.txt"
+#line 586 "src/lexer-keywords.txt"
{"throw", TokenType::Throw, Opcode::Throw},
{""},
#line 68 "src/lexer-keywords.txt"
@@ -1234,15 +1234,15 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 47 "src/lexer-keywords.txt"
{"drop", TokenType::Drop, Opcode::Drop},
{""}, {""}, {""},
-#line 612 "src/lexer-keywords.txt"
+#line 613 "src/lexer-keywords.txt"
{"v128.store32_lane", TokenType::SimdStoreLane, Opcode::V128Store32Lane},
{""}, {""}, {""}, {""}, {""},
-#line 573 "src/lexer-keywords.txt"
+#line 574 "src/lexer-keywords.txt"
{"shared", TokenType::Shared},
-#line 615 "src/lexer-keywords.txt"
+#line 616 "src/lexer-keywords.txt"
{"i8x16.swizzle", TokenType::Binary, Opcode::I8X16Swizzle},
{""}, {""}, {""}, {""},
-#line 577 "src/lexer-keywords.txt"
+#line 578 "src/lexer-keywords.txt"
{"table.fill", TokenType::TableFill, Opcode::TableFill},
{""}, {""}, {""}, {""}, {""}, {""},
#line 394 "src/lexer-keywords.txt"
@@ -1252,7 +1252,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 119 "src/lexer-keywords.txt"
{"f32x4.demote_f64x2_zero", TokenType::Unary, Opcode::F32X4DemoteF64X2Zero},
{""}, {""}, {""},
-#line 588 "src/lexer-keywords.txt"
+#line 589 "src/lexer-keywords.txt"
{"unreachable", TokenType::Unreachable, Opcode::Unreachable},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""},
@@ -1286,10 +1286,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 251 "src/lexer-keywords.txt"
{"i32.atomic.rmw16.or_u", TokenType::AtomicRmw, Opcode::I32AtomicRmw16OrU},
{""}, {""}, {""}, {""}, {""}, {""},
-#line 568 "src/lexer-keywords.txt"
+#line 569 "src/lexer-keywords.txt"
{"rethrow", TokenType::Rethrow, Opcode::Rethrow},
{""}, {""}, {""},
-#line 579 "src/lexer-keywords.txt"
+#line 580 "src/lexer-keywords.txt"
{"table.grow", TokenType::TableGrow, Opcode::TableGrow},
#line 345 "src/lexer-keywords.txt"
{"i32x4.dot_i16x8_s", TokenType::Binary, Opcode::I32X4DotI16X8S},
@@ -1375,8 +1375,10 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 297 "src/lexer-keywords.txt"
{"i32.popcnt", TokenType::Unary, Opcode::I32Popcnt},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
- {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
- {""}, {""},
+ {""}, {""}, {""}, {""},
+#line 559 "src/lexer-keywords.txt"
+ {"pagesize", TokenType::PageSize},
+ {""}, {""}, {""}, {""}, {""}, {""},
#line 556 "src/lexer-keywords.txt"
{"nop", TokenType::Nop, Opcode::Nop},
{""}, {""},
@@ -1520,7 +1522,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 479 "src/lexer-keywords.txt"
{"i64x2.extend_high_i32x4_s", TokenType::Unary, Opcode::I64X2ExtendHighI32X4S},
{""},
-#line 614 "src/lexer-keywords.txt"
+#line 615 "src/lexer-keywords.txt"
{"i8x16.shuffle", TokenType::SimdShuffleOp, Opcode::I8X16Shuffle},
#line 380 "src/lexer-keywords.txt"
{"i64.atomic.rmw16.cmpxchg_u", TokenType::AtomicRmwCmpxchg, Opcode::I64AtomicRmw16CmpxchgU},
@@ -1567,7 +1569,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 184 "src/lexer-keywords.txt"
{"funcref", Type::FuncRef},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
-#line 602 "src/lexer-keywords.txt"
+#line 603 "src/lexer-keywords.txt"
{"v128.load16_splat", TokenType::Load, Opcode::V128Load16Splat},
{""}, {""}, {""}, {""}, {""},
#line 368 "src/lexer-keywords.txt"
@@ -1576,7 +1578,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 367 "src/lexer-keywords.txt"
{"i32x4.extend_low_i16x8_s", TokenType::Unary, Opcode::I32X4ExtendLowI16X8S},
{""}, {""}, {""}, {""},
-#line 607 "src/lexer-keywords.txt"
+#line 608 "src/lexer-keywords.txt"
{"v128.load16_lane", TokenType::SimdLoadLane, Opcode::V128Load16Lane},
{""}, {""}, {""}, {""}, {""}, {""},
#line 50 "src/lexer-keywords.txt"
@@ -1617,7 +1619,7 @@ Perfect_Hash::InWordSet (const char *str, size_t len)
#line 27 "src/lexer-keywords.txt"
{"assert_trap", TokenType::AssertTrap},
{""}, {""}, {""}, {""},
-#line 591 "src/lexer-keywords.txt"
+#line 592 "src/lexer-keywords.txt"
{"v128.bitselect", TokenType::Ternary, Opcode::V128BitSelect},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
diff --git a/src/shared-validator.cc b/src/shared-validator.cc
index 914b5346..6492cbeb 100644
--- a/src/shared-validator.cc
+++ b/src/shared-validator.cc
@@ -134,13 +134,25 @@ Result SharedValidator::OnTable(const Location& loc,
return result;
}
-Result SharedValidator::OnMemory(const Location& loc, const Limits& limits) {
+Result SharedValidator::OnMemory(const Location& loc,
+ const Limits& limits,
+ uint32_t page_size) {
Result result = Result::Ok;
if (memories_.size() > 0 && !options_.features.multi_memory_enabled()) {
result |= PrintError(loc, "only one memory block allowed");
}
- result |= CheckLimits(
- loc, limits, limits.is_64 ? WABT_MAX_PAGES64 : WABT_MAX_PAGES32, "pages");
+
+ if (page_size != WABT_DEFAULT_PAGE_SIZE) {
+ if (!options_.features.custom_page_sizes_enabled()) {
+ result |= PrintError(loc, "only default page size (64 KiB) is allowed");
+ } else if (page_size != 1) {
+ result |= PrintError(loc, "only page sizes of 1 B or 64 KiB are allowed");
+ }
+ }
+
+ uint64_t absolute_max = WABT_BYTES_TO_MIN_PAGES(
+ (limits.is_64 ? UINT64_MAX : UINT32_MAX), page_size);
+ result |= CheckLimits(loc, limits, absolute_max, "pages");
if (limits.is_shared) {
if (!options_.features.threads_enabled()) {
diff --git a/src/test-interp.cc b/src/test-interp.cc
index 614eed33..9346b7b1 100644
--- a/src/test-interp.cc
+++ b/src/test-interp.cc
@@ -491,7 +491,8 @@ TEST_F(InterpTest, Rot13) {
std::string string_data = "Hello, WebAssembly!";
- auto memory = Memory::New(store_, MemoryType{Limits{1}});
+ auto memory =
+ Memory::New(store_, MemoryType{Limits{1}, WABT_DEFAULT_PAGE_SIZE});
auto fill_buf = [&](Thread& thread, const Values& params, Values& results,
Trap::Ptr* out_trap) -> Result {
@@ -659,7 +660,7 @@ TEST_F(InterpGCTest, Collect_InstanceImport) {
[](Thread& thread, const Values&, Values&,
Trap::Ptr*) -> Result { return Result::Ok; });
auto t = Table::New(store_, TableType{ValueType::FuncRef, Limits{0}});
- auto m = Memory::New(store_, MemoryType{Limits{0}});
+ auto m = Memory::New(store_, MemoryType{Limits{0}, WABT_DEFAULT_PAGE_SIZE});
auto g = Global::New(store_, GlobalType{ValueType::I32, Mutability::Const},
Value::Make(5));
diff --git a/src/tools/spectest-interp.cc b/src/tools/spectest-interp.cc
index 2dd4202b..d859f148 100644
--- a/src/tools/spectest-interp.cc
+++ b/src/tools/spectest-interp.cc
@@ -1313,7 +1313,8 @@ CommandRunner::CommandRunner() : store_(s_features) {
spectest["table64"] = interp::Table::New(
store_, TableType{ValueType::FuncRef, Limits{10, 20, false, true}});
- spectest["memory"] = interp::Memory::New(store_, MemoryType{Limits{1, 2}});
+ spectest["memory"] = interp::Memory::New(
+ store_, MemoryType{Limits{1, 2}, WABT_DEFAULT_PAGE_SIZE});
spectest["global_i32"] =
interp::Global::New(store_, GlobalType{ValueType::I32, Mutability::Const},
diff --git a/src/validator.cc b/src/validator.cc
index 980618c8..71c78411 100644
--- a/src/validator.cc
+++ b/src/validator.cc
@@ -732,7 +732,8 @@ Result Validator::CheckModule() {
case ExternalKind::Memory: {
auto&& memory = cast<MemoryImport>(f->import.get())->memory;
- result_ |= validator_.OnMemory(field.loc, memory.page_limits);
+ result_ |= validator_.OnMemory(field.loc, memory.page_limits,
+ memory.page_size);
break;
}
@@ -772,7 +773,8 @@ Result Validator::CheckModule() {
// Memory section.
for (const ModuleField& field : module->fields) {
if (auto* f = dyn_cast<MemoryModuleField>(&field)) {
- result_ |= validator_.OnMemory(field.loc, f->memory.page_limits);
+ result_ |= validator_.OnMemory(field.loc, f->memory.page_limits,
+ f->memory.page_size);
}
}
diff --git a/src/wast-parser.cc b/src/wast-parser.cc
index eb67dceb..e3606b7c 100644
--- a/src/wast-parser.cc
+++ b/src/wast-parser.cc
@@ -1146,6 +1146,37 @@ Result WastParser::ParseLimits(Limits* out_limits) {
return Result::Ok;
}
+Result WastParser::ParsePageSize(uint32_t* out_page_size) {
+ WABT_TRACE(ParsePageSize);
+
+ Result result = Result::Ok;
+
+ if (PeekMatchLpar(TokenType::PageSize)) {
+ if (!options_->features.custom_page_sizes_enabled()) {
+ Error(GetLocation(), "Specifying memory page size is not allowed");
+ return Result::Error;
+ }
+ EXPECT(Lpar);
+ EXPECT(PageSize);
+ auto token = GetToken();
+ if (!token.HasLiteral()) {
+ Error(GetLocation(), "malformed custom page size");
+ return Result::Error;
+ }
+ auto sv = token.literal().text;
+ result |= ParseInt32(sv, out_page_size, ParseIntType::UnsignedOnly);
+ if (*out_page_size > UINT32_MAX || *out_page_size <= 0 ||
+ (*out_page_size & (*out_page_size - 1))) {
+ Error(GetLocation(), "malformed custom page size");
+ return Result::Error;
+ }
+ Consume();
+ EXPECT(Rpar);
+ }
+
+ return result;
+}
+
Result WastParser::ParseNat(uint64_t* out_nat, bool is_64) {
WABT_TRACE(ParseNat);
if (!PeekMatch(TokenType::Nat)) {
@@ -1674,8 +1705,10 @@ Result WastParser::ParseImportModuleField(Module* module) {
Consume();
ParseBindVarOpt(&name);
auto import = std::make_unique<MemoryImport>(name);
+ import->memory.page_size = WABT_DEFAULT_PAGE_SIZE;
CHECK_RESULT(ParseLimitsIndex(&import->memory.page_limits));
CHECK_RESULT(ParseLimits(&import->memory.page_limits));
+ CHECK_RESULT(ParsePageSize(&import->memory.page_size));
EXPECT(Rpar);
field = std::make_unique<ImportModuleField>(std::move(import), loc);
break;
@@ -1728,15 +1761,26 @@ Result WastParser::ParseMemoryModuleField(Module* module) {
if (PeekMatchLpar(TokenType::Import)) {
CheckImportOrdering(module);
auto import = std::make_unique<MemoryImport>(name);
+ import->memory.page_size = WABT_DEFAULT_PAGE_SIZE;
CHECK_RESULT(ParseInlineImport(import.get()));
CHECK_RESULT(ParseLimitsIndex(&import->memory.page_limits));
CHECK_RESULT(ParseLimits(&import->memory.page_limits));
+ CHECK_RESULT(ParsePageSize(&import->memory.page_size));
auto field =
std::make_unique<ImportModuleField>(std::move(import), GetLocation());
module->AppendField(std::move(field));
} else {
auto field = std::make_unique<MemoryModuleField>(loc, name);
+ field->memory.page_size = WABT_DEFAULT_PAGE_SIZE;
CHECK_RESULT(ParseLimitsIndex(&field->memory.page_limits));
+ if (PeekMatchLpar(TokenType::PageSize)) {
+ // this is the data abbreviation (no limits)
+ CHECK_RESULT(ParsePageSize(&field->memory.page_size));
+ if (!PeekMatchLpar(TokenType::Data)) {
+ ConsumeIfLpar();
+ return ErrorExpected({"inline data segment"});
+ }
+ }
if (MatchLpar(TokenType::Data)) {
auto data_segment_field = std::make_unique<DataSegmentModuleField>(loc);
DataSegment& data_segment = data_segment_field->data_segment;
@@ -1747,16 +1791,17 @@ Result WastParser::ParseMemoryModuleField(Module* module) {
ParseTextListOpt(&data_segment.data);
EXPECT(Rpar);
- uint32_t byte_size = WABT_ALIGN_UP_TO_PAGE(data_segment.data.size());
- uint32_t page_size = WABT_BYTES_TO_PAGES(byte_size);
- field->memory.page_limits.initial = page_size;
- field->memory.page_limits.max = page_size;
+ uint32_t num_pages = WABT_BYTES_TO_MIN_PAGES(data_segment.data.size(),
+ field->memory.page_size);
+ field->memory.page_limits.initial = num_pages;
+ field->memory.page_limits.max = num_pages;
field->memory.page_limits.has_max = true;
module->AppendField(std::move(field));
module->AppendField(std::move(data_segment_field));
} else {
CHECK_RESULT(ParseLimits(&field->memory.page_limits));
+ CHECK_RESULT(ParsePageSize(&field->memory.page_size));
module->AppendField(std::move(field));
}
}
diff --git a/src/wat-writer.cc b/src/wat-writer.cc
index b458eca1..a013717a 100644
--- a/src/wat-writer.cc
+++ b/src/wat-writer.cc
@@ -1496,6 +1496,11 @@ void WatWriter::WriteMemory(const Memory& memory) {
WriteInlineExports(ExternalKind::Memory, memory_index_);
WriteInlineImport(ExternalKind::Memory, memory_index_);
WriteLimits(memory.page_limits);
+ if (memory.page_size != WABT_DEFAULT_PAGE_SIZE) {
+ WriteOpenSpace("pagesize");
+ Writef("%u", memory.page_size);
+ WriteCloseSpace();
+ }
WriteCloseNewline();
memory_index_++;
}