Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
5 changes: 3 additions & 2 deletions src/ir/module-splitting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
3 changes: 3 additions & 0 deletions src/ir/module-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ Function* copyFunction(Function* func,
std::optional<std::vector<Index>> fileIndexMap) {
auto ret = std::make_unique<Function>();
ret->name = newName.is() ? newName : func->name;
ret->hasExplicitName = func->hasExplicitName;
ret->type = func->type;
ret->vars = func->vars;
ret->localNames = func->localNames;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
9 changes: 8 additions & 1 deletion src/tools/wasm-merge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,14 @@ void copyModuleContents(Module& input, Name inputName) {
}
}

// TODO: type names, features, debug info, custom sections, dylink info, etc.
// Copy type names.
for (auto& [type, names] : input.typeNames) {
if (!merged.typeNames.count(type)) {
merged.typeNames[type] = names;
}
}

// TODO: features, debug info, custom sections, dylink info, etc.
}

void reportTypeMismatch(bool& valid, const char* kind, Importable* import) {
Expand Down
32 changes: 20 additions & 12 deletions src/wasm/wasm-binary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::pair<Index, Function*>> functionsWithNames;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the very same code as for globals.

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
Expand Down
1 change: 1 addition & 0 deletions src/wasm/wasm-s-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,7 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
// make a new function
currFunction = std::unique_ptr<Function>(
Builder(wasm).makeFunction(name, std::move(params), type, std::move(vars)));
currFunction->hasExplicitName = hasExplicitName;
currFunction->profile = profile;

// parse body
Expand Down
137 changes: 137 additions & 0 deletions test/lit/merge/names.wat
Original file line number Diff line number Diff line change
@@ -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: )
27 changes: 27 additions & 0 deletions test/lit/merge/names.wat.second
Original file line number Diff line number Diff line change
@@ -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)))
)
12 changes: 6 additions & 6 deletions test/lit/wasm-split/basic.wast
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@

;; KEEP-NONE-PRIMARY: (module
;; KEEP-NONE-PRIMARY-NEXT: (type $0 (func (param i32) (result i32)))
;; KEEP-NONE-PRIMARY-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32)))
;; KEEP-NONE-PRIMARY-NEXT: (import "placeholder" "0" (func $fimport$0 (param i32) (result i32)))
;; KEEP-NONE-PRIMARY-NEXT: (table $table 1 1 funcref)
;; KEEP-NONE-PRIMARY-NEXT: (elem $0 (i32.const 0) $placeholder_0)
;; KEEP-NONE-PRIMARY-NEXT: (elem $0 (i32.const 0) $fimport$0)
;; KEEP-NONE-PRIMARY-NEXT: (export "%table" (table $table))
;; KEEP-NONE-PRIMARY-NEXT: )

Expand All @@ -91,9 +91,9 @@

;; KEEP-FOO-PRIMARY: (module
;; KEEP-FOO-PRIMARY-NEXT: (type $0 (func (param i32) (result i32)))
;; KEEP-FOO-PRIMARY-NEXT: (import "placeholder" "1" (func $placeholder_1 (param i32) (result i32)))
;; KEEP-FOO-PRIMARY-NEXT: (import "placeholder" "1" (func $fimport$0 (param i32) (result i32)))
;; KEEP-FOO-PRIMARY-NEXT: (table $table 2 2 funcref)
;; KEEP-FOO-PRIMARY-NEXT: (elem $0 (i32.const 0) $foo $placeholder_1)
;; KEEP-FOO-PRIMARY-NEXT: (elem $0 (i32.const 0) $foo $fimport$0)
;; KEEP-FOO-PRIMARY-NEXT: (export "%foo" (func $foo))
;; KEEP-FOO-PRIMARY-NEXT: (export "%table" (table $table))
;; KEEP-FOO-PRIMARY-NEXT: (func $foo (param $0 i32) (result i32)
Expand Down Expand Up @@ -121,9 +121,9 @@

;; KEEP-BAR-PRIMARY: (module
;; KEEP-BAR-PRIMARY-NEXT: (type $0 (func (param i32) (result i32)))
;; KEEP-BAR-PRIMARY-NEXT: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32)))
;; KEEP-BAR-PRIMARY-NEXT: (import "placeholder" "0" (func $fimport$0 (param i32) (result i32)))
;; KEEP-BAR-PRIMARY-NEXT: (table $table 1 1 funcref)
;; KEEP-BAR-PRIMARY-NEXT: (elem $0 (i32.const 0) $placeholder_0)
;; KEEP-BAR-PRIMARY-NEXT: (elem $0 (i32.const 0) $fimport$0)
;; KEEP-BAR-PRIMARY-NEXT: (export "%bar" (func $bar))
;; KEEP-BAR-PRIMARY-NEXT: (export "%table" (table $table))
;; KEEP-BAR-PRIMARY-NEXT: (func $bar (param $0 i32) (result i32)
Expand Down
4 changes: 2 additions & 2 deletions test/lit/wasm-split/jspi-secondary-export.wast
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@

;; PRIMARY: (import "env" "__load_secondary_module" (func $import$__load_secondary_module (param externref)))

;; PRIMARY: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32)))
;; PRIMARY: (import "placeholder" "0" (func $fimport$1 (param i32) (result i32)))

;; PRIMARY: (global $suspender (mut externref) (ref.null noextern))

;; PRIMARY: (global $global$1 (mut i32) (i32.const 0))

;; PRIMARY: (table $0 1 funcref)

;; PRIMARY: (elem $0 (i32.const 0) $placeholder_0)
;; PRIMARY: (elem $0 (i32.const 0) $fimport$1)

;; PRIMARY: (export "foo" (func $export$foo))

Expand Down
4 changes: 2 additions & 2 deletions test/lit/wasm-split/jspi.wast
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@

;; PRIMARY: (import "env" "__load_secondary_module" (func $import$__load_secondary_module (param externref)))

;; PRIMARY: (import "placeholder" "0" (func $placeholder_0 (param i32) (result i32)))
;; PRIMARY: (import "placeholder" "0" (func $fimport$1 (param i32) (result i32)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like a loss of a useful name. Perhaps it's better to keep it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's useful in tests, but it's not useful for production. Are tests enough motivation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so. In production no names are shipped anyhow so adding more names in non-production builds has little downside, so long as they are meaningful, which looks like the case here.


;; PRIMARY: (global $suspender (mut externref) (ref.null noextern))

;; PRIMARY: (global $global$1 (mut i32) (i32.const 0))

;; PRIMARY: (table $0 1 funcref)

;; PRIMARY: (elem $0 (i32.const 0) $placeholder_0)
;; PRIMARY: (elem $0 (i32.const 0) $fimport$1)

;; PRIMARY: (export "foo" (func $export$foo))

Expand Down
4 changes: 2 additions & 2 deletions test/passes/func-metrics.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)))
Expand Down
Binary file modified test/unit/input/gc_target_feature.wasm
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this change?

Copy link
Contributor Author

@vouillon vouillon Apr 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function name section is no longer written when there is no name.

Binary file not shown.