diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2019-04-05 19:48:54 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-05 19:48:54 -0700 |
commit | 37443aef8c22f100dc59e81aff6af5a252f3217d (patch) | |
tree | ae68bcc8b6bbc4f2b7fdd1f50349b9980e59f10f /src/wasm/wasm-binary.cpp | |
parent | 5b24f039ba1f55520a61f6dd6bb8ca46556c592b (diff) | |
download | binaryen-37443aef8c22f100dc59e81aff6af5a252f3217d.tar.gz binaryen-37443aef8c22f100dc59e81aff6af5a252f3217d.tar.bz2 binaryen-37443aef8c22f100dc59e81aff6af5a252f3217d.zip |
Passive segments (#1976)
Adds support for the bulk memory proposal's passive segments. Uses a
new (data passive ...) s-expression syntax to mark sections as
passive.
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 67 |
1 files changed, 48 insertions, 19 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 385ee0ccb..63adbb08f 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -316,13 +316,30 @@ static bool isEmpty(Memory::Segment& segment) { } static bool isConstantOffset(Memory::Segment& segment) { - return segment.offset->is<Const>(); + return segment.offset && segment.offset->is<Const>(); } void WasmBinaryWriter::writeDataSegments() { if (wasm->memory.segments.size() == 0) return; + + Index emitted = 0; + auto emit = [&](Memory::Segment& segment) { + uint32_t flags = 0; + if (segment.isPassive) { + flags |= BinaryConsts::IsPassive; + } + o << U32LEB(flags); + if (!segment.isPassive) { + writeExpression(segment.offset); + o << int8_t(BinaryConsts::End); + } + writeInlineBuffer(&segment.data[0], segment.data.size()); + emitted++; + }; + Index numConstant = 0, numDynamic = 0; + bool hasPassiveSegments = false; for (auto& segment : wasm->memory.segments) { if (!isEmpty(segment)) { if (isConstantOffset(segment)) { @@ -331,6 +348,21 @@ void WasmBinaryWriter::writeDataSegments() { numDynamic++; } } + hasPassiveSegments |= segment.isPassive; + } + + if (hasPassiveSegments) { + if (wasm->memory.segments.size() > WebLimitations::MaxDataSegments) { + std::cerr << "too many data segments, wasm VMs may not accept this binary" << std::endl; + } + // TODO: merge segments in a pass that can fix up memory.init instructions + auto section = startSection(BinaryConsts::Section::Data); + o << U32LEB(wasm->memory.segments.size()); + for (auto& segment : wasm->memory.segments) { + emit(segment); + } + finishSection(section); + return; } // check if we have too many dynamic data segments, which we can do nothing about auto num = numConstant + numDynamic; @@ -347,14 +379,6 @@ void WasmBinaryWriter::writeDataSegments() { o << U32LEB(num); // first, emit all non-constant-offset segments; then emit the constants, // which we may merge if forced to - Index emitted = 0; - auto emit = [&](Memory::Segment& segment) { - o << U32LEB(0); // Linear memory 0 in the MVP - writeExpression(segment.offset); - o << int8_t(BinaryConsts::End); - writeInlineBuffer(&segment.data[0], segment.data.size()); - emitted++; - }; auto& segments = wasm->memory.segments; for (auto& segment : segments) { if (isEmpty(segment)) continue; @@ -1536,20 +1560,25 @@ void WasmBinaryBuilder::readDataSegments() { if (debug) std::cerr << "== readDataSegments" << std::endl; auto num = getU32LEB(); for (size_t i = 0; i < num; i++) { - auto memoryIndex = getU32LEB(); - WASM_UNUSED(memoryIndex); - if (memoryIndex != 0) { - throwError("bad memory index, must be 0"); - } Memory::Segment curr; - auto offset = readExpression(); + uint32_t flags = getU32LEB(); + if (flags > 2) { + throwError("bad segment flags, must be 0, 1, or 2, not " + + std::to_string(flags)); + } + curr.isPassive = flags & BinaryConsts::IsPassive; + if (flags & BinaryConsts::HasMemIndex) { + curr.index = getU32LEB(); + } + if (!curr.isPassive) { + curr.offset = readExpression(); + } auto size = getU32LEB(); - std::vector<char> buffer; - buffer.resize(size); + curr.data.resize(size); for (size_t j = 0; j < size; j++) { - buffer[j] = char(getInt8()); + curr.data[j] = char(getInt8()); } - wasm.memory.segments.emplace_back(offset, (const char*)&buffer[0], size); + wasm.memory.segments.push_back(curr); } } |