diff options
Diffstat (limited to 'src/wasm/wasm-binary.cpp')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 108 |
1 files changed, 8 insertions, 100 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 63adbb08f..b1fc03017 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -311,19 +311,16 @@ void WasmBinaryWriter::writeExports() { finishSection(start); } -static bool isEmpty(Memory::Segment& segment) { - return segment.data.size() == 0; -} - -static bool isConstantOffset(Memory::Segment& segment) { - 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) { + if (wasm->memory.segments.size() > WebLimitations::MaxDataSegments) { + std::cerr << "Some VMs may not accept this binary because it has a large " + << "number of data segments. Run the limit-segments pass to " + << "merge segments." << std::endl; + } + auto start = startSection(BinaryConsts::Section::Data); + o << U32LEB(wasm->memory.segments.size()); + for (auto& segment : wasm->memory.segments) { uint32_t flags = 0; if (segment.isPassive) { flags |= BinaryConsts::IsPassive; @@ -334,95 +331,6 @@ void WasmBinaryWriter::writeDataSegments() { 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)) { - numConstant++; - } else { - 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; - if (numDynamic + 1 >= WebLimitations::MaxDataSegments) { - std::cerr << "too many non-constant-offset data segments, wasm VMs may not accept this binary" << std::endl; - } - // we'll merge constant segments if we must - if (numConstant + numDynamic >= WebLimitations::MaxDataSegments) { - numConstant = WebLimitations::MaxDataSegments - numDynamic - 1; - num = numConstant + numDynamic; - assert(num == WebLimitations::MaxDataSegments - 1); - } - auto start = startSection(BinaryConsts::Section::Data); - o << U32LEB(num); - // first, emit all non-constant-offset segments; then emit the constants, - // which we may merge if forced to - auto& segments = wasm->memory.segments; - for (auto& segment : segments) { - if (isEmpty(segment)) continue; - if (isConstantOffset(segment)) continue; - emit(segment); - } - // from here on, we concern ourselves with non-empty constant-offset - // segments, the ones which we may need to merge - auto isRelevant = [](Memory::Segment& segment) { - return !isEmpty(segment) && isConstantOffset(segment); - }; - for (Index i = 0; i < segments.size(); i++) { - auto& segment = segments[i]; - if (!isRelevant(segment)) continue; - if (emitted + 2 < WebLimitations::MaxDataSegments) { - emit(segment); - } else { - // we can emit only one more segment! merge everything into one - // start the combined segment at the bottom of them all - auto start = segment.offset->cast<Const>()->value.getInteger(); - for (Index j = i + 1; j < segments.size(); j++) { - auto& segment = segments[j]; - if (!isRelevant(segment)) continue; - auto offset = segment.offset->cast<Const>()->value.getInteger(); - start = std::min(start, offset); - } - // create the segment and add in all the data - Const c; - c.value = Literal(int32_t(start)); - c.type = i32; - Memory::Segment combined(&c); - for (Index j = i; j < segments.size(); j++) { - auto& segment = segments[j]; - if (!isRelevant(segment)) continue; - auto offset = segment.offset->cast<Const>()->value.getInteger(); - auto needed = offset + segment.data.size() - start; - if (combined.data.size() < needed) { - combined.data.resize(needed); - } - std::copy(segment.data.begin(), segment.data.end(), combined.data.begin() + (offset - start)); - } - emit(combined); - break; - } } finishSection(start); } |