summaryrefslogtreecommitdiff
path: root/src/ir/module-splitting.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/module-splitting.cpp')
-rw-r--r--src/ir/module-splitting.cpp109
1 files changed, 62 insertions, 47 deletions
diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp
index 7215629e4..d4d03991e 100644
--- a/src/ir/module-splitting.cpp
+++ b/src/ir/module-splitting.cpp
@@ -87,20 +87,18 @@ namespace ModuleSplitting {
namespace {
template<class F> void forEachElement(Module& module, F f) {
- for (auto& table : module.tables) {
- for (auto& segment : table->segments) {
- Name base = "";
- Index offset = 0;
- if (auto* c = segment.offset->dynCast<Const>()) {
- offset = c->value.geti32();
- } else if (auto* g = segment.offset->dynCast<GlobalGet>()) {
- base = g->name;
- }
- for (size_t i = 0; i < segment.data.size(); ++i) {
- f(table->name, base, offset + i, segment.data[i]);
- }
+ ModuleUtils::iterActiveElementSegments(module, [&](ElementSegment* segment) {
+ Name base = "";
+ Index offset = 0;
+ if (auto* c = segment->offset->dynCast<Const>()) {
+ offset = c->value.geti32();
+ } else if (auto* g = segment->offset->dynCast<GlobalGet>()) {
+ base = g->name;
}
- }
+ for (size_t i = 0; i < segment->data.size(); ++i) {
+ f(segment->table, base, offset + i, segment->data[i]);
+ }
+ });
}
struct TableSlotManager {
@@ -116,9 +114,10 @@ struct TableSlotManager {
};
Module& module;
Table* activeTable = nullptr;
- Table::Segment* activeSegment = nullptr;
+ ElementSegment* activeSegment = nullptr;
Slot activeBase;
std::map<Name, Slot> funcIndices;
+ std::vector<ElementSegment*> activeTableSegments;
TableSlotManager(Module& module);
@@ -148,22 +147,29 @@ void TableSlotManager::addSlot(Name func, Slot slot) {
}
TableSlotManager::TableSlotManager(Module& module) : module(module) {
+ // TODO: Reject or handle passive element segments
+
if (module.tables.empty()) {
return;
}
activeTable = module.tables.front().get();
+ ModuleUtils::iterTableSegments(
+ module, activeTable->name, [&](ElementSegment* segment) {
+ activeTableSegments.push_back(segment);
+ });
+
// If there is exactly one table segment and that segment has a non-constant
// offset, append new items to the end of that segment. In all other cases,
// append new items at constant offsets after all existing items at constant
// offsets.
- if (activeTable->segments.size() == 1 &&
- !activeTable->segments[0].offset->is<Const>()) {
- assert(activeTable->segments[0].offset->is<GlobalGet>() &&
+ if (activeTableSegments.size() == 1 &&
+ !activeTableSegments[0]->offset->is<Const>()) {
+ assert(activeTableSegments[0]->offset->is<GlobalGet>() &&
"Unexpected initializer instruction");
- activeSegment = &activeTable->segments[0];
+ activeSegment = activeTableSegments[0];
activeBase = {activeTable->name,
- activeTable->segments[0].offset->cast<GlobalGet>()->name,
+ activeTableSegments[0]->offset->cast<GlobalGet>()->name,
0};
} else {
// Finds the segment with the highest occupied table slot so that new items
@@ -171,13 +177,13 @@ TableSlotManager::TableSlotManager(Module& module) : module(module) {
// overwriting any other items. TODO: be more clever about filling gaps in
// the table, if that is ever useful.
Index maxIndex = 0;
- for (auto& segment : activeTable->segments) {
- assert(segment.offset->is<Const>() &&
+ for (auto& segment : activeTableSegments) {
+ assert(segment->offset->is<Const>() &&
"Unexpected non-const segment offset with multiple segments");
- Index segmentBase = segment.offset->cast<Const>()->value.geti32();
- if (segmentBase + segment.data.size() >= maxIndex) {
- maxIndex = segmentBase + segment.data.size();
- activeSegment = &segment;
+ Index segmentBase = segment->offset->cast<Const>()->value.geti32();
+ if (segmentBase + segment->data.size() >= maxIndex) {
+ maxIndex = segmentBase + segment->data.size();
+ activeSegment = segment;
activeBase = {activeTable->name, "", segmentBase};
}
}
@@ -190,9 +196,7 @@ TableSlotManager::TableSlotManager(Module& module) : module(module) {
}
Table* TableSlotManager::makeTable() {
- module.addTable(Builder::makeTable(Name::fromInt(0)));
-
- return module.tables.front().get();
+ return module.addTable(Builder::makeTable(Name::fromInt(0)));
}
TableSlotManager::Slot TableSlotManager::getSlot(Name func) {
@@ -208,9 +212,16 @@ TableSlotManager::Slot TableSlotManager::getSlot(Name func) {
activeBase = {activeTable->name, "", 0};
}
- assert(activeTable->segments.size() == 0);
- activeTable->segments.emplace_back(Builder(module).makeConst(int32_t(0)));
- activeSegment = &activeTable->segments.back();
+ assert(std::all_of(module.elementSegments.begin(),
+ module.elementSegments.end(),
+ [&](std::unique_ptr<ElementSegment>& segment) {
+ return segment->table != activeTable->name;
+ }));
+ auto segment = std::make_unique<ElementSegment>(
+ activeTable->name, Builder(module).makeConst(int32_t(0)));
+ segment->setName(Name::fromInt(0), false);
+ activeSegment = segment.get();
+ module.addElementSegment(std::move(segment));
}
Slot newSlot = {activeBase.tableName,
@@ -470,13 +481,12 @@ void ModuleSplitter::setupTablePatching() {
}
auto secondaryTable =
- ModuleUtils::copyTableWithoutSegments(tableManager.activeTable, secondary);
+ ModuleUtils::copyTable(tableManager.activeTable, secondary);
if (tableManager.activeBase.global.size()) {
- assert(tableManager.activeTable->segments.size() == 1 &&
+ assert(tableManager.activeTableSegments.size() == 1 &&
"Unexpected number of segments with non-const base");
- assert(secondary.tables.size() == 1 &&
- secondary.tables.front()->segments.empty());
+ assert(secondary.tables.size() == 1 && secondary.elementSegments.empty());
// Since addition is not currently allowed in initializer expressions, we
// need to start the new secondary segment where the primary segment starts.
// The secondary segment will contain the same primary functions as the
@@ -485,29 +495,31 @@ void ModuleSplitter::setupTablePatching() {
// to be imported into the second module. TODO: use better strategies here,
// such as using ref.func in the start function or standardizing addition in
// initializer expressions.
- const Table::Segment& primarySeg =
- tableManager.activeTable->segments.front();
+ const ElementSegment* primarySeg = tableManager.activeTableSegments.front();
std::vector<Name> secondaryElems;
- secondaryElems.reserve(primarySeg.data.size());
+ secondaryElems.reserve(primarySeg->data.size());
// Copy functions from the primary segment to the secondary segment,
// replacing placeholders and creating new exports and imports as necessary.
auto replacement = replacedElems.begin();
for (Index i = 0;
- i < primarySeg.data.size() && replacement != replacedElems.end();
+ i < primarySeg->data.size() && replacement != replacedElems.end();
++i) {
if (replacement->first == i) {
- // primarySeg.data[i] is a placeholder, so use the secondary function.
+ // primarySeg->data[i] is a placeholder, so use the secondary function.
secondaryElems.push_back(replacement->second);
++replacement;
} else {
- exportImportFunction(primarySeg.data[i]);
- secondaryElems.push_back(primarySeg.data[i]);
+ exportImportFunction(primarySeg->data[i]);
+ secondaryElems.push_back(primarySeg->data[i]);
}
}
- auto offset = ExpressionManipulator::copy(primarySeg.offset, secondary);
- secondaryTable->segments.emplace_back(offset, secondaryElems);
+ auto offset = ExpressionManipulator::copy(primarySeg->offset, secondary);
+ auto secondaryElem = std::make_unique<ElementSegment>(
+ secondaryTable->name, offset, secondaryElems);
+ secondaryElem->setName(primarySeg->name, primarySeg->hasExplicitName);
+ secondary.addElementSegment(std::move(secondaryElem));
return;
}
@@ -517,7 +529,11 @@ void ModuleSplitter::setupTablePatching() {
std::vector<Name> currData;
auto finishSegment = [&]() {
auto* offset = Builder(secondary).makeConst(int32_t(currBase));
- secondaryTable->segments.emplace_back(offset, currData);
+ auto secondaryElem =
+ std::make_unique<ElementSegment>(secondaryTable->name, offset, currData);
+ secondaryElem->setName(Name::fromInt(secondary.elementSegments.size()),
+ false);
+ secondary.addElementSegment(std::move(secondaryElem));
};
for (auto curr = replacedElems.begin(); curr != replacedElems.end(); ++curr) {
if (curr->first != currBase + currData.size()) {
@@ -577,8 +593,7 @@ void ModuleSplitter::shareImportableItems() {
for (auto& table : primary.tables) {
auto secondaryTable = secondary.getTableOrNull(table->name);
if (!secondaryTable) {
- secondaryTable =
- ModuleUtils::copyTableWithoutSegments(table.get(), secondary);
+ secondaryTable = ModuleUtils::copyTable(table.get(), secondary);
}
makeImportExport(*table, *secondaryTable, "table", ExternalKind::Table);