diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp index 3d876bf7a6d..8ef0e7b8c5c 100644 --- a/src/ir/module-splitting.cpp +++ b/src/ir/module-splitting.cpp @@ -395,8 +395,9 @@ void ModuleSplitter::exportImportFunction(Name funcName) { // Import the function if it is not already imported into the secondary // module. if (secondary.getFunctionOrNull(funcName) == nullptr) { - auto func = - Builder::makeFunction(funcName, primary.getFunction(funcName)->type, {}); + auto primaryFunc = primary.getFunction(funcName); + auto func = Builder::makeFunction(funcName, primaryFunc->type, {}); + func->hasExplicitName = primaryFunc->hasExplicitName; func->module = config.importNamespace; func->base = exportName; secondary.addFunction(std::move(func)); @@ -542,7 +543,7 @@ void ModuleSplitter::setupTablePatching() { placeholder->base = std::to_string(index); placeholder->name = Names::getValidFunctionName( primary, std::string("placeholder_") + placeholder->base.toString()); - placeholder->hasExplicitName = false; + placeholder->hasExplicitName = true; placeholder->type = secondaryFunc->type; elem = placeholder->name; primary.addFunction(std::move(placeholder)); diff --git a/src/ir/module-utils.cpp b/src/ir/module-utils.cpp index fdee4f86995..8d9e88d182b 100644 --- a/src/ir/module-utils.cpp +++ b/src/ir/module-utils.cpp @@ -48,6 +48,7 @@ Function* copyFunction(Function* func, std::optional> fileIndexMap) { auto ret = std::make_unique(); ret->name = newName.is() ? newName : func->name; + ret->hasExplicitName = func->hasExplicitName; ret->type = func->type; ret->vars = func->vars; ret->localNames = func->localNames; @@ -77,6 +78,7 @@ Function* copyFunction(Function* func, Global* copyGlobal(Global* global, Module& out) { auto* ret = new Global(); ret->name = global->name; + ret->hasExplicitName = global->hasExplicitName; ret->type = global->type; ret->mutable_ = global->mutable_; ret->module = global->module; @@ -93,6 +95,7 @@ Global* copyGlobal(Global* global, Module& out) { Tag* copyTag(Tag* tag, Module& out) { auto* ret = new Tag(); ret->name = tag->name; + ret->hasExplicitName = tag->hasExplicitName; ret->sig = tag->sig; ret->module = tag->module; ret->base = tag->base; @@ -209,8 +212,17 @@ void copyModuleItems(const Module& in, Module& out) { for (auto& curr : in.dataSegments) { copyDataSegment(curr.get(), out); } + + for (auto& [type, names] : in.typeNames) { + if (!out.typeNames.count(type)) { + out.typeNames[type] = names; + } + } } +// TODO: merge this with copyModuleItems, and add options for copying +// exports and other things that are currently different between them, +// if we still need those differences. void copyModule(const Module& in, Module& out) { // we use names throughout, not raw pointers, so simple copying is fine // for everything *but* expressions @@ -222,7 +234,6 @@ void copyModule(const Module& in, Module& out) { out.customSections = in.customSections; out.debugInfoFileNames = in.debugInfoFileNames; out.features = in.features; - out.typeNames = in.typeNames; } void clearModule(Module& wasm) { diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 28a630c4a2b..cb05688e6cb 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -864,19 +864,27 @@ void WasmBinaryWriter::writeNames() { // function names { - auto substart = - startSubsection(BinaryConsts::CustomSections::Subsection::NameFunction); - o << U32LEB(indexes.functionIndexes.size()); - Index emitted = 0; - auto add = [&](Function* curr) { - o << U32LEB(emitted); - writeEscapedName(curr->name.str); - emitted++; + std::vector> functionsWithNames; + Index checked = 0; + auto check = [&](Function* curr) { + if (curr->hasExplicitName) { + functionsWithNames.push_back({checked, curr}); + } + checked++; }; - ModuleUtils::iterImportedFunctions(*wasm, add); - ModuleUtils::iterDefinedFunctions(*wasm, add); - assert(emitted == indexes.functionIndexes.size()); - finishSubsection(substart); + ModuleUtils::iterImportedFunctions(*wasm, check); + ModuleUtils::iterDefinedFunctions(*wasm, check); + assert(checked == indexes.functionIndexes.size()); + if (functionsWithNames.size() > 0) { + auto substart = + startSubsection(BinaryConsts::CustomSections::Subsection::NameFunction); + o << U32LEB(functionsWithNames.size()); + for (auto& [index, global] : functionsWithNames) { + o << U32LEB(index); + writeEscapedName(global->name.str); + } + finishSubsection(substart); + } } // local names diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index c7cedfdbd67..73ffd755da4 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1181,6 +1181,7 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) { // make a new function currFunction = std::unique_ptr( Builder(wasm).makeFunction(name, std::move(params), type, std::move(vars))); + currFunction->hasExplicitName = hasExplicitName; currFunction->profile = profile; // parse body diff --git a/test/lit/merge/names.wat b/test/lit/merge/names.wat new file mode 100644 index 00000000000..24b1dab0d99 --- /dev/null +++ b/test/lit/merge/names.wat @@ -0,0 +1,137 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. +;; RUN: wasm-merge -g %s first %s.second second -all -o %t.wasm +;; RUN: wasm-opt -all %t.wasm -S -o - | filecheck %s +(module + ;; CHECK: (type $0 (func)) + + ;; CHECK: (type $t (struct (field $a i32) (field $b i32))) + + ;; CHECK: (type $2 (func (param (ref $t)))) + + ;; CHECK: (type $u (struct (field $c i64) (field $d i32))) + + ;; CHECK: (type $4 (func (param (ref $u)))) + + ;; CHECK: (global $global$0 i32 (i32.const 0)) + + ;; CHECK: (global $glob2 i32 (i32.const 0)) + + ;; CHECK: (global $global$2 i32 (i32.const 0)) + + ;; CHECK: (global $glob0 i32 (i32.const 0)) + + ;; CHECK: (memory $mem0 0) + + ;; CHECK: (memory $1 0) + + ;; CHECK: (memory $mem2 0) + + ;; CHECK: (memory $3 0) + + ;; CHECK: (table $table0 1 funcref) + + ;; CHECK: (table $1 1 funcref) + + ;; CHECK: (table $table2 1 funcref) + + ;; CHECK: (table $3 1 funcref) + + ;; CHECK: (tag $tag0) + + ;; CHECK: (tag $tag$1) + + ;; CHECK: (tag $tag2) + + ;; CHECK: (tag $tag$3) + + ;; CHECK: (export "m0" (memory $mem0)) + + ;; CHECK: (export "m1" (memory $1)) + + ;; CHECK: (export "f0" (func $func0)) + + ;; CHECK: (export "f1" (func $1)) + + ;; CHECK: (export "t0" (table $table0)) + + ;; CHECK: (export "t1" (table $1)) + + ;; CHECK: (export "g0" (global $glob0)) + + ;; CHECK: (export "g1" (global $global$2)) + + ;; CHECK: (export "tag0" (tag $tag0)) + + ;; CHECK: (export "tag1" (tag $tag$1)) + + ;; CHECK: (export "func" (func $2)) + + ;; CHECK: (export "m2" (memory $mem2)) + + ;; CHECK: (export "m3" (memory $3)) + + ;; CHECK: (export "f2" (func $func2)) + + ;; CHECK: (export "f3" (func $4)) + + ;; CHECK: (export "t2" (table $table2)) + + ;; CHECK: (export "t3" (table $3)) + + ;; CHECK: (export "g2" (global $glob2)) + + ;; CHECK: (export "g3" (global $global$0)) + + ;; CHECK: (export "tag2" (tag $tag2)) + + ;; CHECK: (export "tag3" (tag $tag$3)) + + ;; CHECK: (export "func2" (func $5)) + + ;; CHECK: (func $func0 (type $0) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $func0 (export "f0")) + (func (export "f1")) + + (table $table0 (export "t0") 1 funcref) + (table (export "t1") 1 funcref) + + (global $glob0 (export g0) i32 (i32.const 0)) + (global (export g1) i32 (i32.const 0)) + + (memory $mem0 (export "m0") 0) + (memory (export "m1") 0) + + (elem $elem0 func) + (elem func) + + (data $data0 "") + (data "") + + (tag $tag0 (export tag0)) + (tag (export tag1)) + + (type $t (struct (field $a i32) (field $b i32))) + + (func (export "func") (param $x (ref $t))) +) +;; CHECK: (func $1 (type $0) +;; CHECK-NEXT: (nop) +;; CHECK-NEXT: ) + +;; CHECK: (func $2 (type $2) (param $x (ref $t)) +;; CHECK-NEXT: (nop) +;; CHECK-NEXT: ) + +;; CHECK: (func $func2 (type $0) +;; CHECK-NEXT: (nop) +;; CHECK-NEXT: ) + +;; CHECK: (func $4 (type $0) +;; CHECK-NEXT: (nop) +;; CHECK-NEXT: ) + +;; CHECK: (func $5 (type $4) (param $0 (ref $u)) +;; CHECK-NEXT: (nop) +;; CHECK-NEXT: ) diff --git a/test/lit/merge/names.wat.second b/test/lit/merge/names.wat.second new file mode 100644 index 00000000000..4aed55d5351 --- /dev/null +++ b/test/lit/merge/names.wat.second @@ -0,0 +1,27 @@ +(module + + (func $func2 (export "f2")) + (func (export "f3")) + + (table $table2 (export "t2") 1 funcref) + (table (export "t3") 1 funcref) + + (memory $mem2 (export "m2") 0) + (memory (export "m3") 0) + + (global $glob2 (export g2) i32 (i32.const 0)) + (global (export g3) i32 (i32.const 0)) + + (elem $elem2 func) + (elem func) + + (data $data2 "") + (data "") + + (tag $tag2 (export tag2)) + (tag (export tag3)) + + (type $u (struct (field $c i64) (field $d i32))) + + (func (export "func2") (param (ref $u))) +) diff --git a/test/passes/func-metrics.txt b/test/passes/func-metrics.txt index 69b89557c32..8921b6977b4 100644 --- a/test/passes/func-metrics.txt +++ b/test/passes/func-metrics.txt @@ -244,7 +244,7 @@ func: func_a Block : 1 Call : 5 start: func_a - [removable-bytes-without-it]: 57 + [removable-bytes-without-it]: 60 [total] : 0 (module (type $0 (func)) @@ -274,7 +274,7 @@ func: 0 [vars] : 0 GlobalGet : 1 export: stackSave (0) - [removable-bytes-without-it]: 62 + [removable-bytes-without-it]: 79 [total] : 0 (module (type $0 (func (result i32))) diff --git a/test/unit/input/gc_target_feature.wasm b/test/unit/input/gc_target_feature.wasm index bf2ecf9348b..8fab7a31ab1 100644 Binary files a/test/unit/input/gc_target_feature.wasm and b/test/unit/input/gc_target_feature.wasm differ