diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binary-reader-ir.cc | 16 | ||||
-rw-r--r-- | src/binary-reader-logging.cc | 11 | ||||
-rw-r--r-- | src/binary-reader-objdump.cc | 20 | ||||
-rw-r--r-- | src/binary-reader.cc | 33 | ||||
-rw-r--r-- | src/binary-writer.cc | 23 | ||||
-rw-r--r-- | src/interp/binary-reader-interp.cc | 22 | ||||
-rw-r--r-- | src/interp/interp-wasm-c-api.cc | 5 | ||||
-rw-r--r-- | src/interp/interp.cc | 10 | ||||
-rw-r--r-- | src/lexer-keywords.txt | 1 | ||||
-rw-r--r-- | src/prebuilt/lexer-keywords.cc | 122 | ||||
-rw-r--r-- | src/shared-validator.cc | 18 | ||||
-rw-r--r-- | src/test-interp.cc | 5 | ||||
-rw-r--r-- | src/tools/spectest-interp.cc | 3 | ||||
-rw-r--r-- | src/validator.cc | 6 | ||||
-rw-r--r-- | src/wast-parser.cc | 53 | ||||
-rw-r--r-- | src/wat-writer.cc | 5 |
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_++; } |