From 3c636decdcaec93be3c4c1a77ea1292489a105f3 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Thu, 28 Aug 2025 01:17:35 +0000 Subject: [PATCH 1/8] Update 'names' field in source maps This scans the code after optimizations and removes unused function names from 'names' field in the source map, reducing its size. Emscripten has not been generating 'names' field so far, but after #???, it will generate the field in case `llvm-dwarfdump` supports a new option `--filter-child-tag`. --- src/wasm/wasm-binary.cpp | 45 ++++++++++++++++++++++++++++------ test/lit/source-map-names.wast | 24 ++++++++++++++++++ 2 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 test/lit/source-map-names.wast diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 3ebd5d8ecba..e9273bb6386 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -16,16 +16,13 @@ #include #include -#include -#include "ir/eh-utils.h" #include "ir/module-utils.h" #include "ir/names.h" #include "ir/table-utils.h" #include "ir/type-updating.h" #include "pass.h" #include "support/bits.h" -#include "support/debug.h" #include "support/stdckdint.h" #include "support/string.h" #include "wasm-annotations.h" @@ -1242,6 +1239,44 @@ void WasmBinaryWriter::writeSourceMapProlog() { } } + // Remove unused function names from 'names' field. + if (!wasm->debugInfoSymbolNames.empty()) { + std::vector newSymbolNames; + std::unordered_map oldToNewIndex; + + // Collect all used symbol name indexes. + for (auto& func : wasm->functions) { + for (auto& pair : func->debugLocations) { + if (pair.second && pair.second->symbolNameIndex) { + uint32_t oldIndex = *pair.second->symbolNameIndex; + assert(oldIndex < wasm->debugInfoSymbolNames.size()); + oldToNewIndex[oldIndex] = 0; // placeholder + } + } + } + + // Create the new list of names and the mapping from old to new indices. + uint32_t newIndex = 0; + for (auto& pair : oldToNewIndex) { + // pair.first is the oldIndex + newSymbolNames.push_back(wasm->debugInfoSymbolNames[pair.first]); + pair.second = newIndex++; // update placeholder to new index + } + + // Update all debug locations to point to the new indices. + for (auto& func : wasm->functions) { + for (auto& pair : func->debugLocations) { + if (pair.second && pair.second->symbolNameIndex) { + uint32_t oldIndex = *pair.second->symbolNameIndex; + pair.second->symbolNameIndex = oldToNewIndex[oldIndex]; + } + } + } + + // Replace the old symbol names with the new, pruned list. + wasm->debugInfoSymbolNames = std::move(newSymbolNames); + } + auto writeOptionalString = [&](const char* name, const std::string& str) { if (!str.empty()) { *sourceMap << "\"" << name << "\":\"" << str << "\","; @@ -1269,10 +1304,6 @@ void WasmBinaryWriter::writeSourceMapProlog() { writeStringVector("sourcesContent", wasm->debugInfoSourcesContent); } - // TODO: This field is optional; maybe we should omit if it's empty. - // TODO: Binaryen actually does not correctly preserve symbol names when it - // rewrites the mappings. We should maybe just drop them, or else handle - // them correctly. writeStringVector("names", wasm->debugInfoSymbolNames); *sourceMap << "\"mappings\":\""; diff --git a/test/lit/source-map-names.wast b/test/lit/source-map-names.wast new file mode 100644 index 00000000000..d24e2ce2383 --- /dev/null +++ b/test/lit/source-map-names.wast @@ -0,0 +1,24 @@ +;; RUN: wasm-opt %s --remove-unused-module-elements -o %t.wasm -osm %t.map +;; RUN: wasm-dis %t.wasm --source-map %t.map | filecheck %s --check-prefix OUT-WAST +;; RUN: cat %t.map | filecheck %s --check-prefix OUT-MAP + +;; After --remove-unused-module-elements, the output source map's 'names' field +;; should NOT contain 'unused' + +;; OUT-MAP: "names":["used"] + +(module + (export "used" (func $used)) + + (func $unused + ;;@ src.cpp:1:1:unused + (nop) + ) + + (func $used + ;; OUT-WAST: ;;@ src.cpp:2:1:used + ;; OUT-WAST-NEXT: (nop) + ;;@ src.cpp:2:1:used + (nop) + ) +) From f6361860eb1a040b5f60ab89831b547ed8b46089 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Thu, 4 Dec 2025 16:33:35 -0800 Subject: [PATCH 2/8] Update src/wasm/wasm-binary.cpp Co-authored-by: Alon Zakai --- src/wasm/wasm-binary.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index e9273bb6386..c010141e09a 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1257,7 +1257,7 @@ void WasmBinaryWriter::writeSourceMapProlog() { // Create the new list of names and the mapping from old to new indices. uint32_t newIndex = 0; - for (auto& pair : oldToNewIndex) { + for (auto& [oldIndex, newIndex] : oldToNewIndex) { // pair.first is the oldIndex newSymbolNames.push_back(wasm->debugInfoSymbolNames[pair.first]); pair.second = newIndex++; // update placeholder to new index From 38d6742ec4ea06af8e09487bbba3421fff408dbe Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Fri, 5 Dec 2025 00:37:49 +0000 Subject: [PATCH 3/8] Use [_, location] --- src/wasm/wasm-binary.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index c010141e09a..4a8d80ee913 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1246,9 +1246,9 @@ void WasmBinaryWriter::writeSourceMapProlog() { // Collect all used symbol name indexes. for (auto& func : wasm->functions) { - for (auto& pair : func->debugLocations) { - if (pair.second && pair.second->symbolNameIndex) { - uint32_t oldIndex = *pair.second->symbolNameIndex; + for (auto& [_, location] : func->debugLocations) { + if (location && location->symbolNameIndex) { + uint32_t oldIndex = *location->symbolNameIndex; assert(oldIndex < wasm->debugInfoSymbolNames.size()); oldToNewIndex[oldIndex] = 0; // placeholder } From 3a68a12e3e6995f7f4e99c5af475d28c54783d28 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Fri, 5 Dec 2025 00:41:32 +0000 Subject: [PATCH 4/8] Use [oldIndex, newIndex] --- src/wasm/wasm-binary.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 4a8d80ee913..a50fe423ca6 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1256,11 +1256,10 @@ void WasmBinaryWriter::writeSourceMapProlog() { } // Create the new list of names and the mapping from old to new indices. - uint32_t newIndex = 0; + uint32_t index = 0; for (auto& [oldIndex, newIndex] : oldToNewIndex) { - // pair.first is the oldIndex - newSymbolNames.push_back(wasm->debugInfoSymbolNames[pair.first]); - pair.second = newIndex++; // update placeholder to new index + newSymbolNames.push_back(wasm->debugInfoSymbolNames[oldIndex]); + newIndex = index++; } // Update all debug locations to point to the new indices. From 93d135a1169610dfb0d01994a5cffb73b59c872f Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Fri, 5 Dec 2025 00:47:24 +0000 Subject: [PATCH 5/8] unordered_map -> map --- src/wasm/wasm-binary.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index a50fe423ca6..2f44c1298ad 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1242,7 +1242,7 @@ void WasmBinaryWriter::writeSourceMapProlog() { // Remove unused function names from 'names' field. if (!wasm->debugInfoSymbolNames.empty()) { std::vector newSymbolNames; - std::unordered_map oldToNewIndex; + std::map oldToNewIndex; // Collect all used symbol name indexes. for (auto& func : wasm->functions) { From a55a84461086db11691e309b5ffbf2dacae2d48b Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Fri, 5 Dec 2025 00:47:39 +0000 Subject: [PATCH 6/8] Add another test case to check determinism --- test/lit/source-map-names.wast | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/lit/source-map-names.wast b/test/lit/source-map-names.wast index d24e2ce2383..b0a184bb588 100644 --- a/test/lit/source-map-names.wast +++ b/test/lit/source-map-names.wast @@ -5,10 +5,11 @@ ;; After --remove-unused-module-elements, the output source map's 'names' field ;; should NOT contain 'unused' -;; OUT-MAP: "names":["used"] +;; OUT-MAP: "names":["used","used2"] (module (export "used" (func $used)) + (export "used2" (func $used2)) (func $unused ;;@ src.cpp:1:1:unused @@ -21,4 +22,11 @@ ;;@ src.cpp:2:1:used (nop) ) + + (func $used2 + ;; OUT-WAST: ;;@ src.cpp:3:1:used + ;; OUT-WAST-NEXT: (nop) + ;;@ src.cpp:3:1:used2 + (nop) + ) ) From 6a530611361dfe07afaf93d68d4b53a978bf32ed Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Thu, 4 Dec 2025 23:36:03 -0800 Subject: [PATCH 7/8] Update src/wasm/wasm-binary.cpp Co-authored-by: Derek Schuff --- src/wasm/wasm-binary.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 2f44c1298ad..ff5411a045f 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1264,7 +1264,7 @@ void WasmBinaryWriter::writeSourceMapProlog() { // Update all debug locations to point to the new indices. for (auto& func : wasm->functions) { - for (auto& pair : func->debugLocations) { + for (auto& [_, location] : func->debugLocations) { if (pair.second && pair.second->symbolNameIndex) { uint32_t oldIndex = *pair.second->symbolNameIndex; pair.second->symbolNameIndex = oldToNewIndex[oldIndex]; From d0a70ae4da7deb748fa59ac58711a5737859299e Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Fri, 5 Dec 2025 07:37:44 +0000 Subject: [PATCH 8/8] Use [_, location] --- src/wasm/wasm-binary.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index ff5411a045f..a2af860f07f 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1265,9 +1265,9 @@ void WasmBinaryWriter::writeSourceMapProlog() { // Update all debug locations to point to the new indices. for (auto& func : wasm->functions) { for (auto& [_, location] : func->debugLocations) { - if (pair.second && pair.second->symbolNameIndex) { - uint32_t oldIndex = *pair.second->symbolNameIndex; - pair.second->symbolNameIndex = oldToNewIndex[oldIndex]; + if (location && location->symbolNameIndex) { + uint32_t oldIndex = *location->symbolNameIndex; + location->symbolNameIndex = oldToNewIndex[oldIndex]; } } }