diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/Print.cpp | 1 | ||||
-rw-r--r-- | src/wasm-binary.h | 9 | ||||
-rw-r--r-- | src/wasm-s-parser.h | 1 | ||||
-rw-r--r-- | src/wasm.h | 3 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 36 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 36 |
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()); |