summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-binary.cpp
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2019-04-05 19:48:54 -0700
committerGitHub <noreply@github.com>2019-04-05 19:48:54 -0700
commit37443aef8c22f100dc59e81aff6af5a252f3217d (patch)
treeae68bcc8b6bbc4f2b7fdd1f50349b9980e59f10f /src/wasm/wasm-binary.cpp
parent5b24f039ba1f55520a61f6dd6bb8ca46556c592b (diff)
downloadbinaryen-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.cpp67
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);
}
}