summaryrefslogtreecommitdiff
path: root/src/wast-parser.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/wast-parser.cc')
-rw-r--r--src/wast-parser.cc53
1 files changed, 49 insertions, 4 deletions
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));
}
}