diff options
author | Wouter van Oortmerssen <aardappel@gmail.com> | 2020-09-18 15:50:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-09-18 15:50:25 -0700 |
commit | 3b4cb935f83c7fabacbf61146e56dabc0d65a441 (patch) | |
tree | 9aaac74aad59fe2ff2b00ac6e6a77bb808b01747 /src/wasm/wasm-s-parser.cpp | |
parent | 1a928bc3ff4b511e81b3f93db8aea872e88abaaf (diff) | |
download | binaryen-3b4cb935f83c7fabacbf61146e56dabc0d65a441.tar.gz binaryen-3b4cb935f83c7fabacbf61146e56dabc0d65a441.tar.bz2 binaryen-3b4cb935f83c7fabacbf61146e56dabc0d65a441.zip |
Initial implementation of "Memory64" proposal (#3130)
Also includes a lot of new spec tests that eventually need to go into the spec repo
Diffstat (limited to 'src/wasm/wasm-s-parser.cpp')
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 75 |
1 files changed, 56 insertions, 19 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 2883519f2..8bbcc9ac0 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -50,12 +50,13 @@ int unhex(char c) { namespace wasm { -static Address getCheckedAddress(const Element* s, const char* errorText) { - uint64_t num = atoll(s->c_str()); - if (num > std::numeric_limits<Address::address_t>::max()) { - throw ParseException(errorText, s->line, s->col); +static Address getAddress(const Element* s) { return atoll(s->c_str()); } + +static void +checkAddress(Address a, const char* errorText, const Element* errorElem) { + if (a > std::numeric_limits<Address::address32_t>::max()) { + throw ParseException(errorText, errorElem->line, errorElem->col); } - return num; } static bool elementStartsWith(Element& s, IString str) { @@ -1023,12 +1024,18 @@ Expression* SExpressionWasmBuilder::makeDrop(Element& s) { Expression* SExpressionWasmBuilder::makeMemorySize(Element& s) { auto ret = allocator.alloc<MemorySize>(); + if (wasm.memory.is64()) { + ret->make64(); + } ret->finalize(); return ret; } Expression* SExpressionWasmBuilder::makeMemoryGrow(Element& s) { auto ret = allocator.alloc<MemoryGrow>(); + if (wasm.memory.is64()) { + ret->make64(); + } ret->delta = parseExpression(s[1]); ret->finalize(); return ret; @@ -2007,18 +2014,40 @@ void SExpressionWasmBuilder::stringToBinary(const char* input, data.resize(actual); } +Index SExpressionWasmBuilder::parseMemoryIndex(Element& s, Index i) { + if (i < s.size() && s[i]->isStr()) { + if (s[i]->str() == "i64") { + i++; + wasm.memory.indexType = Type::i64; + } else if (s[i]->str() == "i32") { + i++; + wasm.memory.indexType = Type::i32; + } + } + return i; +} + Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) { - wasm.memory.initial = getCheckedAddress(s[i++], "excessive memory init"); + i = parseMemoryIndex(s, i); if (i == s.size()) { - wasm.memory.max = Memory::kUnlimitedSize; - return i; + throw ParseException("missing memory limits", s.line, s.col); } - uint64_t max = atoll(s[i]->c_str()); - if (max > Memory::kMaxSize) { - throw ParseException("total memory must be <= 4GB", s[i]->line, s[i]->col); + auto initElem = s[i++]; + wasm.memory.initial = getAddress(initElem); + if (!wasm.memory.is64()) { + checkAddress(wasm.memory.initial, "excessive memory init", initElem); } - wasm.memory.max = max; - return ++i; + if (i == s.size()) { + wasm.memory.max = Memory::kUnlimitedSize; + } else { + auto maxElem = s[i++]; + wasm.memory.max = getAddress(maxElem); + if (!wasm.memory.is64() && wasm.memory.max > Memory::kMaxSize32) { + throw ParseException( + "total memory must be <= 4GB", maxElem->line, maxElem->col); + } + } + return i; } void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { @@ -2031,6 +2060,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { if (s[i]->dollared()) { wasm.memory.name = s[i++]->str(); } + i = parseMemoryIndex(s, i); Name importModule, importBase; if (s[i]->isList()) { auto& inner = *s[i]; @@ -2057,8 +2087,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { throw ParseException("bad import ending", inner.line, inner.col); } // (memory (data ..)) format + auto j = parseMemoryIndex(inner, 1); auto offset = allocator.alloc<Const>()->set(Literal(int32_t(0))); - parseInnerData(*s[i], 1, offset, false); + parseInnerData(inner, j, offset, false); wasm.memory.initial = wasm.memory.segments[0].data.size(); return; } @@ -2075,7 +2106,11 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) { if (elementStartsWith(curr, DATA)) { offsetValue = 0; } else { - offsetValue = getCheckedAddress(curr[j++], "excessive memory offset"); + auto offsetElem = curr[j++]; + offsetValue = getAddress(offsetElem); + if (!wasm.memory.is64()) { + checkAddress(offsetValue, "excessive memory offset", offsetElem); + } } const char* input = curr[j]->c_str(); auto* offset = allocator.alloc<Const>(); @@ -2263,12 +2298,14 @@ void SExpressionWasmBuilder::parseImport(Element& s) { wasm.table.module = module; wasm.table.base = base; if (j < inner.size() - 1) { - wasm.table.initial = - getCheckedAddress(inner[j++], "excessive table init size"); + auto initElem = inner[j++]; + wasm.table.initial = getAddress(initElem); + checkAddress(wasm.table.initial, "excessive table init size", initElem); } if (j < inner.size() - 1) { - wasm.table.max = - getCheckedAddress(inner[j++], "excessive table max size"); + auto maxElem = inner[j++]; + wasm.table.max = getAddress(maxElem); + checkAddress(wasm.table.max, "excessive table max size", maxElem); } else { wasm.table.max = Table::kUnlimitedSize; } |