diff options
Diffstat (limited to 'src/ir')
-rw-r--r-- | src/ir/ReFinalize.cpp | 3 | ||||
-rw-r--r-- | src/ir/memory-utils.cpp | 26 | ||||
-rw-r--r-- | src/ir/memory-utils.h | 75 | ||||
-rw-r--r-- | src/ir/module-utils.h | 30 | ||||
-rw-r--r-- | src/ir/utils.h | 2 |
5 files changed, 82 insertions, 54 deletions
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index 79a4c9386..ef09ddbae 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -189,6 +189,9 @@ void ReFinalize::visitElementSegment(ElementSegment* curr) { WASM_UNREACHABLE("unimp"); } void ReFinalize::visitMemory(Memory* curr) { WASM_UNREACHABLE("unimp"); } +void ReFinalize::visitDataSegment(DataSegment* curr) { + WASM_UNREACHABLE("unimp"); +} void ReFinalize::visitTag(Tag* curr) { WASM_UNREACHABLE("unimp"); } void ReFinalize::visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); } diff --git a/src/ir/memory-utils.cpp b/src/ir/memory-utils.cpp index b7c92fe9e..8dc3baeb9 100644 --- a/src/ir/memory-utils.cpp +++ b/src/ir/memory-utils.cpp @@ -37,34 +37,36 @@ bool flatten(Module& wasm) { } } - auto& memory = wasm.memory; + auto& dataSegments = wasm.dataSegments; - if (memory.segments.size() == 0) { + if (dataSegments.size() == 0) { return true; } std::vector<char> data; - for (auto& segment : memory.segments) { - if (segment.isPassive) { + for (auto& segment : dataSegments) { + if (segment->isPassive) { return false; } - auto* offset = segment.offset->dynCast<Const>(); + auto* offset = segment->offset->dynCast<Const>(); if (!offset) { return false; } } - for (auto& segment : memory.segments) { - auto* offset = segment.offset->dynCast<Const>(); + for (auto& segment : dataSegments) { + auto* offset = segment->offset->dynCast<Const>(); Index start = offset->value.getInteger(); - Index end = start + segment.data.size(); + Index end = start + segment->data.size(); if (end > data.size()) { data.resize(end); } - std::copy(segment.data.begin(), segment.data.end(), data.begin() + start); + std::copy(segment->data.begin(), segment->data.end(), data.begin() + start); } - memory.segments.resize(1); - memory.segments[0].offset->cast<Const>()->value = Literal(int32_t(0)); - memory.segments[0].data.swap(data); + dataSegments.resize(1); + dataSegments[0]->offset->cast<Const>()->value = Literal(int32_t(0)); + dataSegments[0]->data.swap(data); + wasm.removeDataSegments( + [&](DataSegment* curr) { return curr->name != dataSegments[0]->name; }); return true; } diff --git a/src/ir/memory-utils.h b/src/ir/memory-utils.h index 9b3325329..5e9086ca4 100644 --- a/src/ir/memory-utils.h +++ b/src/ir/memory-utils.h @@ -43,8 +43,8 @@ inline void ensureExists(Memory& memory) { // Try to merge segments until they fit into web limitations. // Return true if successful. inline bool ensureLimitedSegments(Module& module) { - Memory& memory = module.memory; - if (memory.segments.size() <= WebLimitations::MaxDataSegments) { + auto& dataSegments = module.dataSegments; + if (dataSegments.size() <= WebLimitations::MaxDataSegments) { return true; } @@ -54,25 +54,23 @@ inline bool ensureLimitedSegments(Module& module) { return false; } - auto isEmpty = [](Memory::Segment& segment) { - return segment.data.size() == 0; - }; + auto isEmpty = [](DataSegment& segment) { return segment.data.size() == 0; }; - auto isConstantOffset = [](Memory::Segment& segment) { + auto isConstantOffset = [](DataSegment& segment) { return segment.offset && segment.offset->is<Const>(); }; Index numConstant = 0, numDynamic = 0; bool hasPassiveSegments = false; - for (auto& segment : memory.segments) { - if (!isEmpty(segment)) { - if (isConstantOffset(segment)) { + for (auto& segment : dataSegments) { + if (!isEmpty(*segment)) { + if (isConstantOffset(*segment)) { numConstant++; } else { numDynamic++; } } - hasPassiveSegments |= segment.isPassive; + hasPassiveSegments |= segment->isPassive; } if (hasPassiveSegments) { @@ -93,43 +91,43 @@ inline bool ensureLimitedSegments(Module& module) { assert(num == WebLimitations::MaxDataSegments - 1); } - std::vector<Memory::Segment> mergedSegments; + std::vector<std::unique_ptr<wasm::DataSegment>> mergedSegments; mergedSegments.reserve(WebLimitations::MaxDataSegments); // drop empty segments and pass through dynamic-offset segments - for (auto& segment : memory.segments) { - if (isEmpty(segment)) { + for (auto& segment : dataSegments) { + if (isEmpty(*segment)) { continue; } - if (isConstantOffset(segment)) { + if (isConstantOffset(*segment)) { continue; } - mergedSegments.push_back(segment); + mergedSegments.push_back(std::move(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) { + auto isRelevant = [&](DataSegment& segment) { return !isEmpty(segment) && isConstantOffset(segment); }; - for (Index i = 0; i < memory.segments.size(); i++) { - auto& segment = memory.segments[i]; - if (!isRelevant(segment)) { + for (Index i = 0; i < dataSegments.size(); i++) { + auto& segment = dataSegments[i]; + if (!isRelevant(*segment)) { continue; } if (mergedSegments.size() + 2 < WebLimitations::MaxDataSegments) { - mergedSegments.push_back(segment); + mergedSegments.push_back(std::move(segment)); continue; } // 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 < memory.segments.size(); j++) { - auto& segment = memory.segments[j]; - if (!isRelevant(segment)) { + auto start = segment->offset->cast<Const>()->value.getInteger(); + for (Index j = i + 1; j < dataSegments.size(); j++) { + auto& segment = dataSegments[j]; + if (!isRelevant(*segment)) { continue; } - auto offset = segment.offset->cast<Const>()->value.getInteger(); + auto offset = segment->offset->cast<Const>()->value.getInteger(); start = std::min(start, offset); } // create the segment and add in all the data @@ -137,26 +135,27 @@ inline bool ensureLimitedSegments(Module& module) { c->value = Literal(int32_t(start)); c->type = Type::i32; - Memory::Segment combined(c); - for (Index j = i; j < memory.segments.size(); j++) { - auto& segment = memory.segments[j]; - if (!isRelevant(segment)) { + auto combined = Builder::makeDataSegment(); + combined->offset = c; + for (Index j = i; j < dataSegments.size(); j++) { + auto& segment = dataSegments[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); + 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)); + std::copy(segment->data.begin(), + segment->data.end(), + combined->data.begin() + (offset - start)); } - mergedSegments.push_back(combined); + mergedSegments.push_back(std::move(combined)); break; } - memory.segments.swap(mergedSegments); + dataSegments.swap(mergedSegments); return true; } } // namespace wasm::MemoryUtils diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h index 5030bf84f..4f731748e 100644 --- a/src/ir/module-utils.h +++ b/src/ir/module-utils.h @@ -106,6 +106,20 @@ inline Table* copyTable(const Table* table, Module& out) { return out.addTable(std::move(ret)); } +inline DataSegment* copyDataSegment(const DataSegment* segment, Module& out) { + auto ret = Builder::makeDataSegment(); + ret->name = segment->name; + ret->hasExplicitName = segment->hasExplicitName; + ret->isPassive = segment->isPassive; + if (!segment->isPassive) { + auto offset = ExpressionManipulator::copy(segment->offset, out); + ret->offset = offset; + } + ret->data = segment->data; + + return out.addDataSegment(std::move(ret)); +} + inline void copyModule(const Module& in, Module& out) { // we use names throughout, not raw pointers, so simple copying is fine // for everything *but* expressions @@ -127,11 +141,10 @@ inline void copyModule(const Module& in, Module& out) { for (auto& curr : in.tables) { copyTable(curr.get(), out); } - - out.memory = in.memory; - for (auto& segment : out.memory.segments) { - segment.offset = ExpressionManipulator::copy(segment.offset, out); + for (auto& curr : in.dataSegments) { + copyDataSegment(curr.get(), out); } + out.memory = in.memory; out.start = in.start; out.userSections = in.userSections; out.debugInfoFileNames = in.debugInfoFileNames; @@ -205,6 +218,15 @@ template<typename T> inline void iterDefinedMemories(Module& wasm, T visitor) { } } +template<typename T> +inline void iterActiveDataSegments(Module& wasm, T visitor) { + for (auto& segment : wasm.dataSegments) { + if (!segment->isPassive) { + visitor(segment.get()); + } + } +} + template<typename T> inline void iterImportedTables(Module& wasm, T visitor) { for (auto& import : wasm.tables) { if (import->imported()) { diff --git a/src/ir/utils.h b/src/ir/utils.h index 7abc87b5e..cad4a78aa 100644 --- a/src/ir/utils.h +++ b/src/ir/utils.h @@ -139,6 +139,7 @@ struct ReFinalize void visitTable(Table* curr); void visitElementSegment(ElementSegment* curr); void visitMemory(Memory* curr); + void visitDataSegment(DataSegment* curr); void visitTag(Tag* curr); void visitModule(Module* curr); @@ -163,6 +164,7 @@ struct ReFinalizeNode : public OverriddenVisitor<ReFinalizeNode> { void visitTable(Table* curr) { WASM_UNREACHABLE("unimp"); } void visitElementSegment(ElementSegment* curr) { WASM_UNREACHABLE("unimp"); } void visitMemory(Memory* curr) { WASM_UNREACHABLE("unimp"); } + void visitDataSegment(DataSegment* curr) { WASM_UNREACHABLE("unimp"); } void visitTag(Tag* curr) { WASM_UNREACHABLE("unimp"); } void visitModule(Module* curr) { WASM_UNREACHABLE("unimp"); } |