diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index 40d3a276b3d..34b962d1478 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -729,29 +729,6 @@ void ModuleSplitter::shareImportableItems() { } NameCollector collector(used); - // We shouldn't use collector.walkModuleCode here, because we don't want to - // walk global initializers. At this point, all globals are still in the - // primary module, so if we walk global initializers here, other globals - // appearing in their initializers will all be marked as used in the primary - // module, which is not what we want. - // - // For example, we have (global $a i32 (global.get $b)). Because $a is at - // this point still in the primary module, $b will be marked as "used" in - // the primary module. But $a can be moved to a secondary module later if it - // is used exclusively by that module. Then $b can be also moved, in case it - // doesn't have other uses. But if it is marked as "used" in the primary - // module, it can't. - walkSegments(collector, &module); - for (auto& segment : module.dataSegments) { - if (segment->isActive()) { - used.memories.insert(segment->memory); - } - } - for (auto& segment : module.elementSegments) { - if (segment->isActive()) { - used.tables.insert(segment->table); - } - } // If primary module has exports, they are "used" in it. Secondary modules // don't have exports, so this only applies to the primary module. @@ -785,6 +762,37 @@ void ModuleSplitter::shareImportableItems() { } } + // We shouldn't use collector.walkModuleCode here, because we don't want to + // walk global initializers. At this point, all globals are still in the + // primary module, so if we walk global initializers here, other globals + // appearing in their initializers will all be marked as used in the primary + // module, which is not what we want. + // + // For example, we have (global $a i32 (global.get $b)). Because $a is at + // this point still in the primary module, $b will be marked as "used" in + // the primary module. But $a can be moved to a secondary module later if it + // is used exclusively by that module. Then $b can be also moved, in case it + // doesn't have other uses. But if it is marked as "used" in the primary + // module, it can't. + walkSegments(collector, &module); + for (auto& segment : module.dataSegments) { + if (segment->isActive()) { + used.memories.insert(segment->memory); + } + } + for (auto& segment : module.elementSegments) { + if (segment->isActive()) { + used.tables.insert(segment->table); + } + } + for (auto name : used.tables) { + if (auto* table = primary.getTableOrNull(name)) { + if (table->init) { + collector.walk(table->init); + } + } + } + // Compute the transitive closure of globals referenced in other globals' // initializers. Since globals can reference other globals, we must ensure // that if a global is used in a module, all its dependencies are also diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp index b17d6c772b9..34a93bf5ec9 100644 --- a/src/ir/module-utils.cpp +++ b/src/ir/module-utils.cpp @@ -165,6 +165,9 @@ Table* copyTable(const Table* table, Module& out) { ret->initial = table->initial; ret->max = table->max; ret->addressType = table->addressType; + if (table->init) { + ret->init = ExpressionManipulator::copy(table->init, out); + } return out.addTable(std::move(ret)); } diff --git a/test/lit/wasm-split/split-module-items.wast b/test/lit/wasm-split/split-module-items.wast index fdca4737a28..1c91693987c 100644 --- a/test/lit/wasm-split/split-module-items.wast +++ b/test/lit/wasm-split/split-module-items.wast @@ -9,6 +9,7 @@ ;; the secondary module (module + (import "env" "g" (global $import-global-for-table funcref)) (memory $keep-memory 1 1) (global $keep-global i32 (i32.const 20)) (table $keep-table 1 1 funcref) @@ -16,7 +17,7 @@ (memory $split-memory 1 1) (global $split-global i32 (i32.const 20)) - (table $split-table 1 1 funcref) + (table $split-table 1 1 funcref (global.get $import-global-for-table)) (tag $split-tag (param i32)) (memory $shared-memory 1 1) @@ -44,13 +45,14 @@ ;; SECONDARY: (import "primary" "memory" (memory $shared-memory 1 1)) ;; SECONDARY-NEXT: (import "primary" "table" (table $shared-table 1 1 funcref)) ;; SECONDARY-NEXT: (import "primary" "table_5" (table $timport$1 1 funcref)) + ;; SECONDARY-NEXT: (import "env" "g" (global $import-global-for-table funcref)) ;; SECONDARY-NEXT: (import "primary" "global" (global $shared-global i32)) ;; SECONDARY-NEXT: (import "primary" "keep" (func $keep (exact (param i32) (result i32)))) ;; SECONDARY-NEXT: (import "primary" "tag" (tag $shared-tag (type $1) (param i32))) ;; SECONDARY: (global $split-global i32 (i32.const 20)) ;; SECONDARY-NEXT: (memory $split-memory 1 1) - ;; SECONDARY-NEXT: (table $split-table 1 1 funcref) + ;; SECONDARY-NEXT: (table $split-table 1 1 funcref (global.get $import-global-for-table)) ;; SECONDARY: (tag $split-tag (type $1) (param i32)) (func $keep (param i32) (result i32)