summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/Print.cpp1
-rw-r--r--src/wasm-binary.h9
-rw-r--r--src/wasm-s-parser.h1
-rw-r--r--src/wasm.h3
-rw-r--r--src/wasm/wasm-binary.cpp36
-rw-r--r--src/wasm/wasm-s-parser.cpp36
6 files changed, 57 insertions, 29 deletions
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index 340266fcf..0494e7d78 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -670,6 +670,7 @@ struct PrintSExpression : public Visitor<PrintSExpression> {
printName(curr->name) << ' ';
o << curr->initial;
if (curr->max && curr->max != Memory::kMaxSize) o << ' ' << curr->max;
+ if (curr->shared) o << " shared";
o << ")";
}
void visitMemory(Memory* curr) {
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 889a3aa6c..9e75d6501 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -515,6 +515,11 @@ enum MemoryAccess {
NaturalAlignment = 0
};
+enum MemoryFlags {
+ HasMaximum = 1 << 0,
+ IsShared = 1 << 1
+};
+
} // namespace BinaryConsts
@@ -560,7 +565,7 @@ public:
void write();
void writeHeader();
int32_t writeU32LEBPlaceholder();
- void writeResizableLimits(Address initial, Address maximum, bool hasMaximum);
+ void writeResizableLimits(Address initial, Address maximum, bool hasMaximum, bool shared);
int32_t startSection(BinaryConsts::Section code);
void finishSection(int32_t start);
int32_t startSubsection(BinaryConsts::UserSections::Subsection code);
@@ -712,7 +717,7 @@ public:
// gets a name in the combined function import+defined function space
Name getFunctionIndexName(Index i);
- void getResizableLimits(Address& initial, Address& max, Address defaultIfNoMax);
+ void getResizableLimits(Address& initial, Address& max, bool& shared, Address defaultIfNoMax);
void readImports();
std::vector<FunctionType*> functionTypes; // types of defined functions
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 8b887d690..c79e0a458 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -196,6 +196,7 @@ private:
Expression* makeReturn(Element& s);
WasmType parseOptionalResultType(Element& s, Index& i);
+ Index parseMemoryLimits(Element& s, Index i);
void stringToBinary(const char* input, size_t size, std::vector<char>& data);
void parseMemory(Element& s, bool preParseImport = false);
diff --git a/src/wasm.h b/src/wasm.h
index f1f16a469..56432faf9 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -632,8 +632,9 @@ public:
// See comment in Table.
bool exists;
bool imported;
+ bool shared;
- Memory() : initial(0), max(kMaxSize), exists(false), imported(false) {
+ Memory() : initial(0), max(kMaxSize), exists(false), imported(false), shared(false) {
name = Name::fromInt(0);
}
};
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 3b6bbbb9d..359d9d8f8 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -71,8 +71,11 @@ int32_t WasmBinaryWriter::writeU32LEBPlaceholder() {
return ret;
}
-void WasmBinaryWriter::writeResizableLimits(Address initial, Address maximum, bool hasMaximum) {
- uint32_t flags = hasMaximum ? 1 : 0;
+void WasmBinaryWriter::writeResizableLimits(Address initial, Address maximum,
+ bool hasMaximum, bool shared) {
+ uint32_t flags =
+ (hasMaximum ? (uint32_t) BinaryConsts::HasMaximum : 0U) |
+ (shared ? (uint32_t) BinaryConsts::IsShared : 0U);
o << U32LEB(flags);
o << U32LEB(initial);
if (hasMaximum) {
@@ -113,7 +116,8 @@ void WasmBinaryWriter::writeMemory() {
if (debug) std::cerr << "== writeMemory" << std::endl;
auto start = startSection(BinaryConsts::Section::Memory);
o << U32LEB(1); // Define 1 memory
- writeResizableLimits(wasm->memory.initial, wasm->memory.max, wasm->memory.max != Memory::kMaxSize);
+ writeResizableLimits(wasm->memory.initial, wasm->memory.max,
+ wasm->memory.max != Memory::kMaxSize, wasm->memory.shared);
finishSection(start);
}
@@ -161,11 +165,12 @@ void WasmBinaryWriter::writeImports() {
case ExternalKind::Function: o << U32LEB(getFunctionTypeIndex(import->functionType)); break;
case ExternalKind::Table: {
o << S32LEB(BinaryConsts::EncodedType::AnyFunc);
- writeResizableLimits(wasm->table.initial, wasm->table.max, wasm->table.max != Table::kMaxSize);
+ writeResizableLimits(wasm->table.initial, wasm->table.max, wasm->table.max != Table::kMaxSize, /*shared=*/false);
break;
}
case ExternalKind::Memory: {
- writeResizableLimits(wasm->memory.initial, wasm->memory.max, wasm->memory.max != Memory::kMaxSize);
+ writeResizableLimits(wasm->memory.initial, wasm->memory.max,
+ wasm->memory.max != Memory::kMaxSize, wasm->memory.shared);
break;
}
case ExternalKind::Global:
@@ -368,7 +373,7 @@ void WasmBinaryWriter::writeFunctionTableDeclaration() {
auto start = startSection(BinaryConsts::Section::Table);
o << U32LEB(1); // Declare 1 table.
o << S32LEB(BinaryConsts::EncodedType::AnyFunc);
- writeResizableLimits(wasm->table.initial, wasm->table.max, wasm->table.max != Table::kMaxSize);
+ writeResizableLimits(wasm->table.initial, wasm->table.max, wasm->table.max != Table::kMaxSize, /*shared=*/false);
finishSection(start);
}
@@ -1237,7 +1242,7 @@ void WasmBinaryBuilder::readMemory() {
throw ParseException("Memory cannot be both imported and defined");
}
wasm.memory.exists = true;
- getResizableLimits(wasm.memory.initial, wasm.memory.max, Memory::kMaxSize);
+ getResizableLimits(wasm.memory.initial, wasm.memory.max, wasm.memory.shared, Memory::kMaxSize);
}
void WasmBinaryBuilder::readSignatures() {
@@ -1284,10 +1289,13 @@ Name WasmBinaryBuilder::getFunctionIndexName(Index i) {
}
}
-void WasmBinaryBuilder::getResizableLimits(Address& initial, Address& max, Address defaultIfNoMax) {
+void WasmBinaryBuilder::getResizableLimits(Address& initial, Address& max, bool &shared, Address defaultIfNoMax) {
auto flags = getU32LEB();
initial = getU32LEB();
- bool hasMax = flags & 0x1;
+ bool hasMax = flags & BinaryConsts::HasMaximum;
+ bool isShared = flags & BinaryConsts::IsShared;
+ if (isShared && !hasMax) throw ParseException("shared memory must have max size");
+ shared = isShared;
if (hasMax) max = getU32LEB();
else max = defaultIfNoMax;
}
@@ -1320,13 +1328,15 @@ void WasmBinaryBuilder::readImports() {
if (elementType != BinaryConsts::EncodedType::AnyFunc) throw ParseException("Imported table type is not AnyFunc");
wasm.table.exists = true;
wasm.table.imported = true;
- getResizableLimits(wasm.table.initial, wasm.table.max, Table::kMaxSize);
+ bool is_shared;
+ getResizableLimits(wasm.table.initial, wasm.table.max, is_shared, Table::kMaxSize);
+ if (is_shared) throw ParseException("Tables may not be shared");
break;
}
case ExternalKind::Memory: {
wasm.memory.exists = true;
wasm.memory.imported = true;
- getResizableLimits(wasm.memory.initial, wasm.memory.max, Memory::kMaxSize);
+ getResizableLimits(wasm.memory.initial, wasm.memory.max, wasm.memory.shared, Memory::kMaxSize);
break;
}
case ExternalKind::Global: {
@@ -1759,7 +1769,9 @@ void WasmBinaryBuilder::readFunctionTableDeclaration() {
wasm.table.exists = true;
auto elemType = getS32LEB();
if (elemType != BinaryConsts::EncodedType::AnyFunc) throw ParseException("ElementType must be AnyFunc in MVP");
- getResizableLimits(wasm.table.initial, wasm.table.max, Table::kMaxSize);
+ bool is_shared;
+ getResizableLimits(wasm.table.initial, wasm.table.max, is_shared, Table::kMaxSize);
+ if (is_shared) throw ParseException("Tables may not be shared");
}
void WasmBinaryBuilder::readTableElements() {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 59043f3b8..6bf030302 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -1440,10 +1440,28 @@ void SExpressionWasmBuilder::stringToBinary(const char* input, size_t size, std:
data.resize(actual);
}
+Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) {
+ wasm.memory.initial = getCheckedAddress(s[i++], "excessive memory init");
+ if (i == s.size()) return i;
+ while (i < s.size() && s[i]->isStr()) {
+ auto* curr = s[i]->c_str();
+ i++;
+ if (strstr(curr, "shared")) {
+ wasm.memory.shared = strncmp(curr, "notshared", 9) != 0;
+ break;
+ }
+ uint64_t max = atoll(curr);
+ if (max > Memory::kMaxSize) throw ParseException("total memory must be <= 4GB");
+ wasm.memory.max = max;
+ }
+ return i;
+}
+
void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
if (wasm.memory.exists) throw ParseException("too many memories");
wasm.memory.exists = true;
wasm.memory.imported = preParseImport;
+ wasm.memory.shared = false;
Index i = 1;
if (s[i]->dollared()) {
wasm.memory.name = s[i++]->str();
@@ -1478,14 +1496,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
return;
}
}
- wasm.memory.initial = getCheckedAddress(s[i++], "excessive memory init");
- if (i == s.size()) return;
- if (s[i]->isStr()) {
- uint64_t max = atoll(s[i]->c_str());
- if (max > Memory::kMaxSize) throw ParseException("total memory must be <= 4GB");
- wasm.memory.max = max;
- i++;
- }
+ i = parseMemoryLimits(s, i);
+
+ // Parse memory initializers.
while (i < s.size()) {
Element& curr = *s[i];
size_t j = 1;
@@ -1683,12 +1696,7 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
}
// ends with the table element type
} else if (im->kind == ExternalKind::Memory) {
- if (j < inner.size()) {
- wasm.memory.initial = getCheckedAddress(inner[j++], "excessive memory init size");
- }
- if (j < inner.size()) {
- wasm.memory.max = getCheckedAddress(inner[j++], "excessive memory max size");
- }
+ j = parseMemoryLimits(inner, j);
}
if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
wasm.addImport(im.release());