diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h index 23e30b7a868d..53a812b2777d 100644 --- a/llvm/include/llvm/BinaryFormat/Wasm.h +++ b/llvm/include/llvm/BinaryFormat/Wasm.h @@ -97,6 +97,7 @@ struct WasmDataSegment { uint32_t MemoryIndex; WasmInitExpr Offset; ArrayRef Content; + StringRef Name; }; struct WasmElemSegment { @@ -184,6 +185,7 @@ enum : unsigned { WASM_SYMBOL_INFO = 0x2, WASM_DATA_SIZE = 0x3, WASM_DATA_ALIGNMENT = 0x4, + WASM_SEGMENT_NAMES = 0x5, }; enum : unsigned { diff --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h index 709ad8ec3b77..171f823a27da 100644 --- a/llvm/include/llvm/ObjectYAML/WasmYAML.h +++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h @@ -160,9 +160,10 @@ struct LinkingSection : CustomSection { return C && C->Name == "linking"; } - std::vector SymbolInfos; uint32_t DataSize; uint32_t DataAlignment; + std::vector SymbolInfos; + std::vector SegmentNames; }; struct TypeSection : Section { diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 7ed20d32fd24..6ec93246c063 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -102,6 +102,7 @@ struct WasmFunctionTypeDenseMapInfo { // wasm data segment. struct WasmDataSegment { MCSectionWasm *Section; + StringRef Name; uint32_t Offset; SmallVector Data; }; @@ -279,7 +280,8 @@ private: uint32_t NumFuncImports); void writeCodeRelocSection(); void writeDataRelocSection(); - void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment, + void writeLinkingMetaDataSection(ArrayRef Segments, + uint32_t DataSize, uint32_t DataAlignment, ArrayRef WeakSymbols, bool HasStackPointer, uint32_t StackPointerGlobal); @@ -911,7 +913,8 @@ void WasmObjectWriter::writeDataRelocSection() { } void WasmObjectWriter::writeLinkingMetaDataSection( - uint32_t DataSize, uint32_t DataAlignment, ArrayRef WeakSymbols, + ArrayRef Segments, uint32_t DataSize, + uint32_t DataAlignment, ArrayRef WeakSymbols, bool HasStackPointer, uint32_t StackPointerGlobal) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); @@ -943,6 +946,14 @@ void WasmObjectWriter::writeLinkingMetaDataSection( endSection(SubSection); } + if (Segments.size()) { + startSection(SubSection, wasm::WASM_SEGMENT_NAMES); + encodeULEB128(Segments.size(), getStream()); + for (const WasmDataSegment &Segment : Segments) + writeString(Segment.Name); + endSection(SubSection); + } + endSection(Section); } @@ -1129,6 +1140,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, DataSize = alignTo(DataSize, Section.getAlignment()); DataSegments.emplace_back(); WasmDataSegment &Segment = DataSegments.back(); + Segment.Name = Section.getSectionName(); Segment.Offset = DataSize; Segment.Section = &Section; addData(Segment.Data, Section, DataAlignment); @@ -1288,7 +1300,8 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, writeNameSection(Functions, Imports, NumFuncImports); writeCodeRelocSection(); writeDataRelocSection(); - writeLinkingMetaDataSection(DataSize, DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal); + writeLinkingMetaDataSection(DataSegments, DataSize, DataAlignment, + WeakSymbols, HasStackPointer, StackPointerGlobal); // TODO: Translate the .comment section to the output. // TODO: Translate debug sections to the output. diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index bd51fbdac0b4..d2d3aba0396d 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -396,6 +396,15 @@ Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr, case wasm::WASM_DATA_ALIGNMENT: LinkingData.DataAlignment = readVaruint32(Ptr); break; + case wasm::WASM_SEGMENT_NAMES: { + uint32_t Count = readVaruint32(Ptr); + if (Count > DataSegments.size()) + return make_error("Too many segment names", + object_error::parse_failed); + for (uint32_t i = 0; i < Count; i++) + DataSegments[i].Data.Name = readString(Ptr); + break; + } case wasm::WASM_STACK_POINTER: default: Ptr += Size; diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp index 8aea8cfb4bc5..a5c1d13598c0 100644 --- a/llvm/lib/ObjectYAML/WasmYAML.cpp +++ b/llvm/lib/ObjectYAML/WasmYAML.cpp @@ -60,6 +60,7 @@ static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) { IO.mapRequired("DataSize", Section.DataSize); IO.mapRequired("DataAlignment", Section.DataAlignment); IO.mapOptional("SymbolInfo", Section.SymbolInfos); + IO.mapOptional("SegmentNames", Section.SegmentNames); } static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) { diff --git a/llvm/test/MC/WebAssembly/array-fill.ll b/llvm/test/MC/WebAssembly/array-fill.ll index 4feabc0748e0..38274c34305f 100644 --- a/llvm/test/MC/WebAssembly/array-fill.ll +++ b/llvm/test/MC/WebAssembly/array-fill.ll @@ -9,6 +9,14 @@ target triple = "wasm32-unknown-unknown-wasm" @gBd = hidden global [2 x %struct.bd] [%struct.bd { i8 1 }, %struct.bd { i8 2 }], align 1 -; CHECK: - Type: DATA -; CHECK: Content: '0102' -; CHECK: DataSize: 2 +; CHECK: - Type: DATA +; CHECK: Content: '0102' + +; CHECK: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: DataSize: 2 +; CHECK-NEXT: DataAlignment: 1 +; CHECK-NEXT: SegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .data +; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/bss.ll b/llvm/test/MC/WebAssembly/bss.ll new file mode 100644 index 000000000000..d203efad19b0 --- /dev/null +++ b/llvm/test/MC/WebAssembly/bss.ll @@ -0,0 +1,20 @@ +; RUN: llc -mtriple wasm32-unknown-unknown-wasm -filetype=obj %s -o - | obj2yaml | FileCheck %s + +@g0 = global i8* null, align 4 + +; CHECK: - Type: DATA +; CHECK-NEXT: Segments: +; CHECK-NEXT: - SectionOffset: 6 +; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 0 +; CHECK-NEXT: Content: '00000000' +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: DataSize: 4 +; CHECK-NEXT: DataAlignment: 4 +; CHECK-NEXT: SegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .bss.g0 +; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/explicit-sections.ll b/llvm/test/MC/WebAssembly/explicit-sections.ll index e96072422526..a8342b628183 100644 --- a/llvm/test/MC/WebAssembly/explicit-sections.ll +++ b/llvm/test/MC/WebAssembly/explicit-sections.ll @@ -63,3 +63,16 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 24 ; CHECK-NEXT: Content: '08000000' + +; CHECK: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: DataSize: 28 +; CHECK-NEXT: DataAlignment: 8 +; CHECK-NEXT: SegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .data.global0 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: .sec1 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: .sec2 +; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/unnamed-data.ll b/llvm/test/MC/WebAssembly/unnamed-data.ll index b5f6d3c524c1..a484913e2898 100644 --- a/llvm/test/MC/WebAssembly/unnamed-data.ll +++ b/llvm/test/MC/WebAssembly/unnamed-data.ll @@ -74,4 +74,13 @@ ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 28 ; CHECK-NEXT: DataAlignment: 8 +; CHECK-NEXT: SegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .rodata..L.str1 +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: .rodata..L.str2 +; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: Name: .data.a +; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: Name: .data.b ; CHECK-NEXT: ... diff --git a/llvm/test/MC/WebAssembly/weak-alias.ll b/llvm/test/MC/WebAssembly/weak-alias.ll index 79c597bc09a5..2beef846def8 100644 --- a/llvm/test/MC/WebAssembly/weak-alias.ll +++ b/llvm/test/MC/WebAssembly/weak-alias.ll @@ -101,4 +101,9 @@ entry: ; CHECK-NEXT: Flags: 1 ; CHECK-NEXT: - Name: bar_alias ; CHECK-NEXT: Flags: 1 +; CHECK-NEXT: SegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .data.bar +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: .data.bar_alias_address ; CHECK-NEXT: ... diff --git a/llvm/test/tools/llvm-readobj/sections.test b/llvm/test/tools/llvm-readobj/sections.test index 4eda5dae882a..ac1eca535fc6 100644 --- a/llvm/test/tools/llvm-readobj/sections.test +++ b/llvm/test/tools/llvm-readobj/sections.test @@ -543,6 +543,12 @@ WASM-NEXT: Section { WASM-NEXT: Type: DATA (0xB) WASM-NEXT: Size: 19 WASM-NEXT: Offset: 154 +WASM-NEXT: Segments [ +WASM-NEXT: Segment { +WASM-NEXT: Size: 13 +WASM-NEXT: Offset: 0 +WASM-NEXT: } +WASM-NEXT: ] WASM-NEXT: } WASM-NEXT: Section { WASM-NEXT: Type: CUSTOM (0x0) diff --git a/llvm/tools/llvm-readobj/WasmDumper.cpp b/llvm/tools/llvm-readobj/WasmDumper.cpp index 88fcbf61a6a7..3bff4b80c833 100644 --- a/llvm/tools/llvm-readobj/WasmDumper.cpp +++ b/llvm/tools/llvm-readobj/WasmDumper.cpp @@ -148,7 +148,7 @@ void WasmDumper::printSections() { const WasmSection &WasmSec = Obj->getWasmSection(Section); DictScope SectionD(W, "Section"); W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes)); - W.printNumber("Size", (uint64_t)WasmSec.Content.size()); + W.printNumber("Size", static_cast(WasmSec.Content.size())); W.printNumber("Offset", WasmSec.Offset); switch (WasmSec.Type) { case wasm::WASM_SEC_CUSTOM: @@ -160,6 +160,19 @@ void WasmDumper::printSections() { W.printNumber("DataAlignment", LinkingData.DataAlignment); } break; + case wasm::WASM_SEC_DATA: { + ListScope Group(W, "Segments"); + for (const WasmSegment &Segment : Obj->dataSegments()) { + const wasm::WasmDataSegment& Seg = Segment.Data; + DictScope Group(W, "Segment"); + if (!Seg.Name.empty()) + W.printString("Name", Seg.Name); + W.printNumber("Size", static_cast(Seg.Content.size())); + if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST) + W.printNumber("Offset", Seg.Offset.Value.Int32); + } + break; + } case wasm::WASM_SEC_MEMORY: ListScope Group(W, "Memories"); for (const wasm::WasmLimits &Memory : Obj->memories()) { diff --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp index a1da4b6a748c..8b2a0adf73fa 100644 --- a/llvm/tools/obj2yaml/wasm2yaml.cpp +++ b/llvm/tools/obj2yaml/wasm2yaml.cpp @@ -70,6 +70,16 @@ std::unique_ptr WasmDumper::dumpCustomSection(const Was CustomSec = std::move(NameSec); } else if (WasmSec.Name == "linking") { std::unique_ptr LinkingSec = make_unique(); + size_t Index = 0; + for (const object::WasmSegment &Segment : Obj.dataSegments()) { + if (!Segment.Data.Name.empty()) { + WasmYAML::NameEntry NameEntry; + NameEntry.Name = Segment.Data.Name; + NameEntry.Index = Index; + LinkingSec->SegmentNames.push_back(NameEntry); + } + Index++; + } for (const object::SymbolRef& Sym: Obj.symbols()) { const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym); if (Symbol.Flags != 0) { @@ -234,7 +244,7 @@ ErrorOr WasmDumper::dump() { } case wasm::WASM_SEC_DATA: { auto DataSec = make_unique(); - for (auto &Segment : Obj.dataSegments()) { + for (const object::WasmSegment &Segment : Obj.dataSegments()) { WasmYAML::DataSegment Seg; Seg.SectionOffset = Segment.SectionOffset; Seg.MemoryIndex = Segment.Data.MemoryIndex; diff --git a/llvm/tools/yaml2obj/yaml2wasm.cpp b/llvm/tools/yaml2obj/yaml2wasm.cpp index 0bd882911f9c..9dd7564720aa 100644 --- a/llvm/tools/yaml2obj/yaml2wasm.cpp +++ b/llvm/tools/yaml2obj/yaml2wasm.cpp @@ -157,6 +157,17 @@ int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &S SubSection.Done(); } + + // SEGMENT_NAMES subsection + if (Section.SegmentNames.size()) { + encodeULEB128(wasm::WASM_SEGMENT_NAMES, OS); + encodeULEB128(Section.SegmentNames.size(), SubSection.GetStream()); + for (const WasmYAML::NameEntry &NameEntry : Section.SegmentNames) { + encodeULEB128(NameEntry.Index, SubSection.GetStream()); + writeStringRef(NameEntry.Name, SubSection.GetStream()); + } + SubSection.Done(); + } return 0; }