diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 3ebd5d8ecba..a2af860f07f 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,43 @@ void WasmBinaryWriter::writeSourceMapProlog() { } } + // Remove unused function names from 'names' field. + if (!wasm->debugInfoSymbolNames.empty()) { + std::vector newSymbolNames; + std::map oldToNewIndex; + + // Collect all used symbol name indexes. + for (auto& func : wasm->functions) { + for (auto& [_, location] : func->debugLocations) { + if (location && location->symbolNameIndex) { + uint32_t oldIndex = *location->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 index = 0; + for (auto& [oldIndex, newIndex] : oldToNewIndex) { + newSymbolNames.push_back(wasm->debugInfoSymbolNames[oldIndex]); + newIndex = index++; + } + + // Update all debug locations to point to the new indices. + for (auto& func : wasm->functions) { + for (auto& [_, location] : func->debugLocations) { + if (location && location->symbolNameIndex) { + uint32_t oldIndex = *location->symbolNameIndex; + location->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 +1303,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..b0a184bb588 --- /dev/null +++ b/test/lit/source-map-names.wast @@ -0,0 +1,32 @@ +;; 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","used2"] + +(module + (export "used" (func $used)) + (export "used2" (func $used2)) + + (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) + ) + + (func $used2 + ;; OUT-WAST: ;;@ src.cpp:3:1:used + ;; OUT-WAST-NEXT: (nop) + ;;@ src.cpp:3:1:used2 + (nop) + ) +)