Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/fuzz_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -2525,7 +2525,7 @@ def handle(self, wasm):
TrapsNeverHappen(),
CtorEval(),
Merge(),
Split(),
# Split(), # Will reenable after stabilized
RoundtripText(),
ClusterFuzz(),
Two(),
Expand Down
31 changes: 26 additions & 5 deletions src/ir/module-splitting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,15 @@ struct TableSlotManager {
Expression* makeExpr(Module& module);
};
Module& module;
const std::vector<std::unique_ptr<Module>>& secondaries;
Table* activeTable = nullptr;
ElementSegment* activeSegment = nullptr;
Slot activeBase;
std::map<Name, Slot> funcIndices;
std::vector<ElementSegment*> activeTableSegments;

TableSlotManager(Module& module);
TableSlotManager(Module& module,
const std::vector<std::unique_ptr<Module>>& secondaries);

Table* makeTable();
ElementSegment* makeElementSegment();
Expand Down Expand Up @@ -149,7 +151,9 @@ void TableSlotManager::addSlot(Name func, Slot slot) {
funcIndices.insert({func, slot});
}

TableSlotManager::TableSlotManager(Module& module) : module(module) {
TableSlotManager::TableSlotManager(
Module& module, const std::vector<std::unique_ptr<Module>>& secondaries)
: module(module), secondaries(secondaries) {
// If possible, just create a new table to manage all primary-to-secondary
// calls lazily. Do not re-use slots for functions that will already be in
// existing tables, since that is not correct in the face of table mutations.
Expand Down Expand Up @@ -233,8 +237,25 @@ TableSlotManager::TableSlotManager(Module& module) : module(module) {
}

Table* TableSlotManager::makeTable() {
return module.addTable(
Builder::makeTable(Names::getValidTableName(module, Name::fromInt(0))));
// Because the active table will be imported in secondary modules, its name
// should not collide with any existing tables in primary and secondary
// modules.
std::unordered_set<Name> secondaryTableNames;
for (auto& secondary : secondaries) {
for (auto& table : secondary->tables) {
secondaryTableNames.insert(table->name);
}
}
Name name = Names::getValidName("0", [&](Name test) {
if (module.getTableOrNull(test)) {
return false;
}
if (secondaryTableNames.count(test)) {
Comment thread
aheejin marked this conversation as resolved.
Outdated
return false;
}
return true;
});
return module.addTable(Builder::makeTable(name));
}

ElementSegment* TableSlotManager::makeElementSegment() {
Expand Down Expand Up @@ -347,7 +368,7 @@ struct ModuleSplitter {
void setupTablePatching();

ModuleSplitter(Module& primary, const Config& config)
: config(config), primary(primary), tableManager(primary),
: config(config), primary(primary), tableManager(primary, secondaries),
exportedPrimaryFuncs(initExportedPrimaryFuncs(primary)),
exportedPrimaryItems(initExportedPrimaryItems(primary)) {
classifyFunctions();
Expand Down
45 changes: 45 additions & 0 deletions test/lit/wasm-split/table-name-conflict.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
;; RUN: wasm-split %s -all -g -S -o1 %t.1.wast -o2 %t.2.wast --split-funcs=split
;; RUN: cat %t.1.wast | filecheck %s --check-prefix PRIMARY
;; RUN: cat %t.2.wast | filecheck %s --check-prefix SECONDARY

;; Regression test for a bug when an existing table, which is to be split to the
;; secondary module, has the name '0'. The newly created active table should
;; have a different name.

(module
(table $0 0 externref)
(export "split" (func $split))
(func $split
(table.set $0
(i32.const 0)
(ref.null extern)
)
)
)

;; PRIMARY: (module
;; PRIMARY-NEXT: (type $0 (func))
;; PRIMARY-NEXT: (import "placeholder.deferred" "0" (func $placeholder_0 (type $0)))
;; PRIMARY-NEXT: (table $0_0 1 funcref)
;; PRIMARY-NEXT: (elem $0 (i32.const 0) $placeholder_0)
;; PRIMARY-NEXT: (export "split" (func $trampoline_split))
;; PRIMARY-NEXT: (export "table" (table $0_0))
;; PRIMARY-NEXT: (func $trampoline_split (type $0)
;; PRIMARY-NEXT: (call_indirect $0_0 (type $0)
;; PRIMARY-NEXT: (i32.const 0)
;; PRIMARY-NEXT: )
;; PRIMARY-NEXT: )
;; PRIMARY-NEXT: )

;; SECONDARY: (module
;; SECONDARY-NEXT: (type $0 (func))
;; SECONDARY-NEXT: (import "primary" "table" (table $0_0 1 funcref))
;; SECONDARY-NEXT: (table $0 0 externref)
;; SECONDARY-NEXT: (elem $0 (table $0_0) (i32.const 0) func $split)
;; SECONDARY-NEXT: (func $split (type $0)
;; SECONDARY-NEXT: (table.set $0
;; SECONDARY-NEXT: (i32.const 0)
;; SECONDARY-NEXT: (ref.null noextern)
;; SECONDARY-NEXT: )
;; SECONDARY-NEXT: )
;; SECONDARY-NEXT: )
Loading