summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-s-parser.cpp
diff options
context:
space:
mode:
authorWouter van Oortmerssen <aardappel@gmail.com>2020-09-18 15:50:25 -0700
committerGitHub <noreply@github.com>2020-09-18 15:50:25 -0700
commit3b4cb935f83c7fabacbf61146e56dabc0d65a441 (patch)
tree9aaac74aad59fe2ff2b00ac6e6a77bb808b01747 /src/wasm/wasm-s-parser.cpp
parent1a928bc3ff4b511e81b3f93db8aea872e88abaaf (diff)
downloadbinaryen-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.cpp75
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;
}