diff --git a/lld/test/wasm/call-indirect.ll b/lld/test/wasm/call-indirect.ll --- a/lld/test/wasm/call-indirect.ll +++ b/lld/test/wasm/call-indirect.ll @@ -156,4 +156,7 @@ ; CHECK-NEXT: GlobalNames: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: __stack_pointer +; CHECK-NEXT: DataSegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .data ; CHECK-NEXT: ... diff --git a/lld/test/wasm/data-segment-merging.ll b/lld/test/wasm/data-segment-merging.ll --- a/lld/test/wasm/data-segment-merging.ll +++ b/lld/test/wasm/data-segment-merging.ll @@ -31,7 +31,9 @@ ; MERGE-NEXT: GlobalNames: ; MERGE-NEXT: - Index: 0 ; MERGE-NEXT: Name: __stack_pointer -; MERGE-NOT: - Index: +; MERGE-NEXT: DataSegmentNames: +; MERGE-NEXT: - Index: 0 +; MERGE-NEXT: Name: .rodata ; RUN: wasm-ld -no-gc-sections --no-entry --no-merge-data-segments -o %t.separate.wasm %t.o ; RUN: obj2yaml %t.separate.wasm | FileCheck %s --check-prefix=SEPARATE @@ -71,7 +73,9 @@ ; SEPARATE-NEXT: GlobalNames: ; SEPARATE-NEXT: - Index: 0 ; SEPARATE-NEXT: Name: __stack_pointer -; SEPARATE-NOT: - Index: +; SEPARATE-NEXT: DataSegmentNames: +; SEPARATE-NEXT: - Index: 0 +; SEPARATE-NEXT: Name: .rodata ; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 -o %t.merged.passive.wasm %t.passive.o ; RUN: obj2yaml %t.merged.passive.wasm | FileCheck %s --check-prefix=PASSIVE-MERGE diff --git a/lld/test/wasm/gc-sections.ll b/lld/test/wasm/gc-sections.ll --- a/lld/test/wasm/gc-sections.ll +++ b/lld/test/wasm/gc-sections.ll @@ -87,6 +87,9 @@ ; CHECK-NEXT: Name: __stack_pointer ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Name: used_global +; CHECK-NEXT: DataSegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .data ; CHECK-NEXT: ... ; RUN: wasm-ld -print-gc-sections --no-gc-sections -o %t1.no-gc.wasm \ @@ -162,6 +165,9 @@ ; NO-GC-NEXT: Name: unused_global ; NO-GC-NEXT: - Index: 2 ; NO-GC-NEXT: Name: used_global +; NO-GC-NEXT: DataSegmentNames: +; NO-GC-NEXT: - Index: 0 +; NO-GC-NEXT: Name: .data ; NO-GC-NEXT: ... ; RUN: not wasm-ld --gc-sections --relocatable -o %t1.no-gc.wasm %t.o 2>&1 | FileCheck %s -check-prefix=CHECK-ERROR diff --git a/lld/test/wasm/local-symbols.ll b/lld/test/wasm/local-symbols.ll --- a/lld/test/wasm/local-symbols.ll +++ b/lld/test/wasm/local-symbols.ll @@ -97,4 +97,7 @@ ; CHECK-NEXT: GlobalNames: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: __stack_pointer +; CHECK-NEXT: DataSegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .data ; CHECK-NEXT: ... diff --git a/lld/test/wasm/locals-duplicate.test b/lld/test/wasm/locals-duplicate.test --- a/lld/test/wasm/locals-duplicate.test +++ b/lld/test/wasm/locals-duplicate.test @@ -212,6 +212,9 @@ ; CHECK-NEXT: GlobalNames: ; CHECK-NEXT: - Index: 0 ; CHECK-NEXT: Name: __stack_pointer +; CHECK-NEXT: DataSegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .data ; CHECK-NEXT: ... @@ -546,4 +549,11 @@ ; RELOC-NEXT: Name: get_func2B ; RELOC-NEXT: - Index: 17 ; RELOC-NEXT: Name: get_func3B +; RELOC-NEXT: DataSegmentNames: +; RELOC-NEXT: - Index: 0 +; RELOC-NEXT: Name: .data.colliding_global1 +; RELOC-NEXT: - Index: 1 +; RELOC-NEXT: Name: .data.colliding_global2 +; RELOC-NEXT: - Index: 2 +; RELOC-NEXT: Name: .data.colliding_global3 ; RELOC-NEXT: ... diff --git a/lld/test/wasm/map-file.s b/lld/test/wasm/map-file.s --- a/lld/test/wasm/map-file.s +++ b/lld/test/wasm/map-file.s @@ -40,7 +40,7 @@ # CHECK-NEXT: 400 5a 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.data.somedata) # CHECK-NEXT: 400 5a 4 somedata # CHECK-NEXT: - 60 12 CUSTOM(.debug_info) -# CHECK-NEXT: - 72 2b CUSTOM(name) +# CHECK-NEXT: - 72 35 CUSTOM(name) # RUN: not wasm-ld %t1.o -o /dev/null -Map=/ 2>&1 \ # RUN: | FileCheck -check-prefix=FAIL %s diff --git a/lld/test/wasm/signature-mismatch.ll b/lld/test/wasm/signature-mismatch.ll --- a/lld/test/wasm/signature-mismatch.ll +++ b/lld/test/wasm/signature-mismatch.ll @@ -55,6 +55,9 @@ ; YAML-NEXT: GlobalNames: ; YAML-NEXT: - Index: 0 ; YAML-NEXT: Name: __stack_pointer +; YAML-NEXT: DataSegmentNames: +; YAML-NEXT: - Index: 0 +; YAML-NEXT: Name: .data ; YAML-NEXT: ... ; RELOC: Name: linking diff --git a/lld/test/wasm/weak-symbols.s b/lld/test/wasm/weak-symbols.s --- a/lld/test/wasm/weak-symbols.s +++ b/lld/test/wasm/weak-symbols.s @@ -116,4 +116,7 @@ # CHECK-NEXT: GlobalNames: # CHECK-NEXT: - Index: 0 # CHECK-NEXT: Name: __stack_pointer +# CHECK-NEXT: DataSegmentNames: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Name: .data # CHECK-NEXT: ... diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h --- a/lld/wasm/SyntheticSections.h +++ b/lld/wasm/SyntheticSections.h @@ -296,7 +296,9 @@ // Create the custom "name" section containing debug symbol names. class NameSection : public SyntheticSection { public: - NameSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name") {} + NameSection(ArrayRef segments) + : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name"), + segments(segments) {} bool isNeeded() const override { return !config->stripDebug && !config->stripAll && numNames() > 0; } @@ -304,6 +306,10 @@ unsigned numNames() const { return numNamedGlobals() + numNamedFunctions(); } unsigned numNamedGlobals() const; unsigned numNamedFunctions() const; + unsigned numNamedDataSegments() const; + +protected: + ArrayRef segments; }; class ProducersSection : public SyntheticSection { diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -562,6 +562,16 @@ return numNames; } +unsigned NameSection::numNamedDataSegments() const { + unsigned numNames = 0; + + for (const OutputSegment *s : segments) + if (!s->name.empty()) + ++numNames; + + return numNames; +} + // Create the custom "name" section containing debug symbol names. void NameSection::writeBody() { unsigned count = numNamedFunctions(); @@ -619,6 +629,19 @@ sub.writeTo(bodyOutputStream); } + + count = numNamedDataSegments(); + if (count) { + SubSection sub(WASM_NAMES_DATA_SEGMENT); + writeUleb128(sub.os, count, "name count"); + + for (OutputSegment *s : segments) { + writeUleb128(sub.os, s->index, "global index"); + writeStr(sub.os, s->name, "segment name"); + } + + sub.writeTo(bodyOutputStream); + } } void ProducersSection::addInfo(const WasmProducerInfo &info) { diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -1210,7 +1210,7 @@ out.elemSec = make(); out.dataCountSec = make(segments); out.linkingSec = make(initFunctions, segments); - out.nameSec = make(); + out.nameSec = make(segments); out.producersSec = make(); out.targetFeaturesSec = make(); } diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -202,7 +202,8 @@ enum class NameType { FUNCTION, - GLOBAL + GLOBAL, + DATA_SEGMENT, }; struct WasmDebugName { @@ -313,9 +314,10 @@ // Kind codes used in the custom "name" section enum : unsigned { - WASM_NAMES_FUNCTION = 0x1, - WASM_NAMES_LOCAL = 0x2, - WASM_NAMES_GLOBAL = 0x7, + WASM_NAMES_FUNCTION = 1, + WASM_NAMES_LOCAL = 2, + WASM_NAMES_GLOBAL = 7, + WASM_NAMES_DATA_SEGMENT = 9, }; // Kind codes used in the custom "linking" section diff --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h --- a/llvm/include/llvm/ObjectYAML/WasmYAML.h +++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h @@ -222,6 +222,7 @@ std::vector FunctionNames; std::vector GlobalNames; + std::vector DataSegmentNames; }; struct LinkingSection : CustomSection { diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -357,6 +357,7 @@ Error WasmObjectFile::parseNameSection(ReadContext &Ctx) { llvm::DenseSet SeenFunctions; llvm::DenseSet SeenGlobals; + llvm::DenseSet SeenSegments; if (FunctionTypes.size() && !SeenCodeSection) { return make_error("Names must come after code section", object_error::parse_failed); @@ -368,11 +369,13 @@ const uint8_t *SubSectionEnd = Ctx.Ptr + Size; switch (Type) { case wasm::WASM_NAMES_FUNCTION: - case wasm::WASM_NAMES_GLOBAL: { + case wasm::WASM_NAMES_GLOBAL: + case wasm::WASM_NAMES_DATA_SEGMENT: { uint32_t Count = readVaruint32(Ctx); while (Count--) { uint32_t Index = readVaruint32(Ctx); StringRef Name = readString(Ctx); + wasm::NameType nameType = wasm::NameType::FUNCTION; if (Type == wasm::WASM_NAMES_FUNCTION) { if (!SeenFunctions.insert(Index).second) return make_error( @@ -383,18 +386,24 @@ if (isDefinedFunctionIndex(Index)) getDefinedFunction(Index).DebugName = Name; - } else { + } else if (Type == wasm::WASM_NAMES_GLOBAL) { + nameType = wasm::NameType::GLOBAL; if (!SeenGlobals.insert(Index).second) return make_error("Global named more than once", object_error::parse_failed); if (!isValidGlobalIndex(Index) || Name.empty()) return make_error("Invalid name entry", object_error::parse_failed); + } else { + nameType = wasm::NameType::DATA_SEGMENT; + if (!SeenSegments.insert(Index).second) + return make_error( + "Segment named more than once", object_error::parse_failed); + if (Index > DataSegments.size()) + return make_error("Invalid named data segment", + object_error::parse_failed); } - wasm::NameType T = Type == wasm::WASM_NAMES_FUNCTION - ? wasm::NameType::FUNCTION - : wasm::NameType::GLOBAL; - DebugNames.push_back(wasm::WasmDebugName{T, Index, Name}); + DebugNames.push_back(wasm::WasmDebugName{nameType, Index, Name}); } break; } diff --git a/llvm/lib/ObjectYAML/WasmEmitter.cpp b/llvm/lib/ObjectYAML/WasmEmitter.cpp --- a/llvm/lib/ObjectYAML/WasmEmitter.cpp +++ b/llvm/lib/ObjectYAML/WasmEmitter.cpp @@ -281,6 +281,19 @@ writeStringRef(NameEntry.Name, SubSection.getStream()); } + SubSection.done(); + } + if (Section.DataSegmentNames.size()) { + writeUint8(OS, wasm::WASM_NAMES_DATA_SEGMENT); + + SubSectionWriter SubSection(OS); + + encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream()); + for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) { + encodeULEB128(NameEntry.Index, SubSection.getStream()); + writeStringRef(NameEntry.Name, SubSection.getStream()); + } + SubSection.done(); } } diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp --- a/llvm/lib/ObjectYAML/WasmYAML.cpp +++ b/llvm/lib/ObjectYAML/WasmYAML.cpp @@ -62,6 +62,7 @@ IO.mapRequired("Name", Section.Name); IO.mapOptional("FunctionNames", Section.FunctionNames); IO.mapOptional("GlobalNames", Section.GlobalNames); + IO.mapOptional("DataSegmentNames", Section.DataSegmentNames); } static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) { diff --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp --- a/llvm/tools/obj2yaml/wasm2yaml.cpp +++ b/llvm/tools/obj2yaml/wasm2yaml.cpp @@ -70,9 +70,11 @@ NameEntry.Index = Name.Index; if (Name.Type == llvm::wasm::NameType::FUNCTION) { NameSec->FunctionNames.push_back(NameEntry); - } else { - assert(Name.Type == llvm::wasm::NameType::GLOBAL); + } else if (Name.Type == llvm::wasm::NameType::GLOBAL) { NameSec->GlobalNames.push_back(NameEntry); + } else { + assert(Name.Type == llvm::wasm::NameType::DATA_SEGMENT); + NameSec->DataSegmentNames.push_back(NameEntry); } } CustomSec = std::move(NameSec);