Index: include/llvm/BinaryFormat/Wasm.h =================================================================== --- include/llvm/BinaryFormat/Wasm.h +++ include/llvm/BinaryFormat/Wasm.h @@ -97,6 +97,7 @@ uint32_t MemoryIndex; WasmInitExpr Offset; ArrayRef Content; + StringRef Name; }; struct WasmElemSegment { @@ -184,6 +185,7 @@ WASM_SYMBOL_INFO = 0x2, WASM_DATA_SIZE = 0x3, WASM_DATA_ALIGNMENT = 0x4, + WASM_SEGMENT_NAMES = 0x5, }; enum : unsigned { Index: include/llvm/MC/MCSectionWasm.h =================================================================== --- include/llvm/MC/MCSectionWasm.h +++ include/llvm/MC/MCSectionWasm.h @@ -43,11 +43,17 @@ // itself and does not include the size of the section header. uint64_t SectionOffset; + // For data sections, this is the offset of the corresponding wasm data + // segment + uint64_t MemoryOffset; + friend class MCContext; MCSectionWasm(StringRef Section, unsigned type, SectionKind K, const MCSymbolWasm *group, unsigned UniqueID, MCSymbol *Begin) : MCSection(SV_Wasm, K, Begin), SectionName(Section), Type(type), - UniqueID(UniqueID), Group(group), SectionOffset(0) {} + UniqueID(UniqueID), Group(group), SectionOffset(0) { + assert(type == wasm::WASM_SEC_CODE || type == wasm::WASM_SEC_DATA); + } void setSectionName(StringRef Name) { SectionName = Name; } @@ -74,6 +80,9 @@ uint64_t getSectionOffset() const { return SectionOffset; } void setSectionOffset(uint64_t Offset) { SectionOffset = Offset; } + uint32_t getMemoryOffset() const { return MemoryOffset; } + void setMemoryOffset(uint32_t Offset) { MemoryOffset = Offset; } + static bool classof(const MCSection *S) { return S->getVariant() == SV_Wasm; } }; Index: include/llvm/ObjectYAML/WasmYAML.h =================================================================== --- include/llvm/ObjectYAML/WasmYAML.h +++ include/llvm/ObjectYAML/WasmYAML.h @@ -160,9 +160,10 @@ return C && C->Name == "linking"; } - std::vector SymbolInfos; uint32_t DataSize; uint32_t DataAlignment; + std::vector SymbolInfos; + std::vector SegmentNames; }; struct TypeSection : Section { Index: lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1262,10 +1262,12 @@ bool UniqueSectionNames = TM.getUniqueSectionNames(); SmallString<128> Name = getSectionPrefixForGlobal(Kind); + uint32_t Type = wasm::WASM_SEC_DATA; if (const auto *F = dyn_cast(GO)) { const auto &OptionalPrefix = F->getSectionPrefix(); if (OptionalPrefix) Name += *OptionalPrefix; + Type = wasm::WASM_SEC_CODE; } if (EmitUniqueSection && UniqueSectionNames) { @@ -1277,7 +1279,7 @@ UniqueID = *NextUniqueID; (*NextUniqueID)++; } - return Ctx.getWasmSection(Name, /*Type=*/0, Group, UniqueID); + return Ctx.getWasmSection(Name, Type, Group, UniqueID); } MCSection *TargetLoweringObjectFileWasm::SelectSectionForGlobal( Index: lib/MC/MCObjectFileInfo.cpp =================================================================== --- lib/MC/MCObjectFileInfo.cpp +++ lib/MC/MCObjectFileInfo.cpp @@ -820,24 +820,24 @@ void MCObjectFileInfo::initWasmMCObjectFileInfo(const Triple &T) { // TODO: Set the section types and flags. - TextSection = Ctx->getWasmSection(".text", 0); - DataSection = Ctx->getWasmSection(".data", 0); + TextSection = Ctx->getWasmSection(".text", wasm::WASM_SEC_CODE); + DataSection = Ctx->getWasmSection(".data", wasm::WASM_SEC_DATA); // TODO: Set the section types and flags. - DwarfLineSection = Ctx->getWasmSection(".debug_line", 0); - DwarfStrSection = Ctx->getWasmSection(".debug_str", 0); - DwarfLocSection = Ctx->getWasmSection(".debug_loc", 0); - DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", 0, "section_abbrev"); - DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", 0); - DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", 0, "debug_range"); - DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", 0, "debug_macinfo"); - DwarfAddrSection = Ctx->getWasmSection(".debug_addr", 0); - DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", 0); - DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", 0); - DwarfInfoSection = Ctx->getWasmSection(".debug_info", 0, "section_info"); - DwarfFrameSection = Ctx->getWasmSection(".debug_frame", 0); - DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", 0); - DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", 0); + DwarfLineSection = Ctx->getWasmSection(".debug_line", wasm::WASM_SEC_DATA); + DwarfStrSection = Ctx->getWasmSection(".debug_str", wasm::WASM_SEC_DATA); + DwarfLocSection = Ctx->getWasmSection(".debug_loc", wasm::WASM_SEC_DATA); + DwarfAbbrevSection = Ctx->getWasmSection(".debug_abbrev", wasm::WASM_SEC_DATA, "section_abbrev"); + DwarfARangesSection = Ctx->getWasmSection(".debug_aranges", wasm::WASM_SEC_DATA); + DwarfRangesSection = Ctx->getWasmSection(".debug_ranges", wasm::WASM_SEC_DATA, "debug_range"); + DwarfMacinfoSection = Ctx->getWasmSection(".debug_macinfo", wasm::WASM_SEC_DATA, "debug_macinfo"); + DwarfAddrSection = Ctx->getWasmSection(".debug_addr", wasm::WASM_SEC_DATA); + DwarfCUIndexSection = Ctx->getWasmSection(".debug_cu_index", wasm::WASM_SEC_DATA); + DwarfTUIndexSection = Ctx->getWasmSection(".debug_tu_index", wasm::WASM_SEC_DATA); + DwarfInfoSection = Ctx->getWasmSection(".debug_info", wasm::WASM_SEC_DATA, "section_info"); + DwarfFrameSection = Ctx->getWasmSection(".debug_frame", wasm::WASM_SEC_DATA); + DwarfPubNamesSection = Ctx->getWasmSection(".debug_pubnames", wasm::WASM_SEC_DATA); + DwarfPubTypesSection = Ctx->getWasmSection(".debug_pubtypes", wasm::WASM_SEC_DATA); // TODO: Define more sections. } Index: lib/MC/MCWasmStreamer.cpp =================================================================== --- lib/MC/MCWasmStreamer.cpp +++ lib/MC/MCWasmStreamer.cpp @@ -156,7 +156,7 @@ void MCWasmStreamer::EmitIdent(StringRef IdentString) { MCSection *Comment = getAssembler().getContext().getWasmSection( - ".comment", 0, 0); + ".comment", wasm::WASM_SEC_DATA); PushSection(); SwitchSection(Comment); if (!SeenIdent) { Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -98,6 +98,7 @@ struct WasmDataSegment { MCSectionWasm *Section; + StringRef Name; uint32_t Offset; SmallVector Data; }; @@ -159,7 +160,8 @@ void print(raw_ostream &Out) const { Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend - << ", Type=" << Type << ", FixupSection=" << FixupSection; + << ", Type=" << Type + << ", FixupSection=" << FixupSection->getSectionName(); } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) @@ -240,6 +242,8 @@ void writeHeader(const MCAssembler &Asm); + void addGlobal(StringRef Name, uint32_t Value); + void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) override; @@ -274,10 +278,10 @@ uint32_t NumFuncImports); void writeCodeRelocSection(); void writeDataRelocSection(); - void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment, - ArrayRef WeakSymbols, - bool HasStackPointer, - uint32_t StackPointerGlobal); + void writeLinkingMetaDataSection( + const ArrayRef Segments, uint32_t DataSize, + uint32_t DataAlignment, ArrayRef WeakSymbols, + bool HasStackPointer, uint32_t StackPointerGlobal); uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry); void applyRelocations(ArrayRef Relocations, @@ -495,6 +499,39 @@ return Value; } +static void addData(SmallVector &DataBytes, MCSectionWasm &DataSection, + uint32_t &DataAlignment) { + DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment())); + DataAlignment = std::max(DataAlignment, DataSection.getAlignment()); + DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n"); + + for (const MCFragment &Frag : DataSection) { + if (Frag.hasInstructions()) + report_fatal_error("only data supported in data sections"); + + if (auto *Align = dyn_cast(&Frag)) { + if (Align->getValueSize() != 1) + report_fatal_error("only byte values supported for alignment"); + // If nops are requested, use zeros, as this is the data section. + uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); + uint64_t Size = std::min(alignTo(DataBytes.size(), + Align->getAlignment()), + DataBytes.size() + + Align->getMaxBytesToEmit()); + DataBytes.resize(Size, Value); + } else if (auto *Fill = dyn_cast(&Frag)) { + DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue()); + } else { + const auto &DataFrag = cast(Frag); + const SmallVectorImpl &Contents = DataFrag.getContents(); + + DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end()); + } + } + + DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n"); +} + uint32_t WasmObjectWriter::getRelocationIndexValue( const WasmRelocationEntry &RelEntry) { switch (RelEntry.Type) { @@ -778,9 +815,7 @@ report_fatal_error(".size expression must be evaluatable"); encodeULEB128(Size, getStream()); - FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset); - Asm.writeSectionData(&FuncSection, Layout); } @@ -885,6 +920,7 @@ } void WasmObjectWriter::writeLinkingMetaDataSection( + const ArrayRef Segments, uint32_t DataSize, uint32_t DataAlignment, ArrayRef WeakSymbols, bool HasStackPointer, uint32_t StackPointerGlobal) { SectionBookkeeping Section; @@ -917,6 +953,14 @@ 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); } @@ -1029,7 +1073,7 @@ // In the special .global_variables section, we've encoded global // variables used by the function. Translate them into the Globals // list. - MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0); + MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", wasm::WASM_SEC_DATA); if (!GlobalVars->getFragmentList().empty()) { if (GlobalVars->getFragmentList().size() != 1) report_fatal_error("only one .global_variables fragment supported"); @@ -1085,7 +1129,7 @@ // In the special .stack_pointer section, we've encoded the stack pointer // index. - MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0); + MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", wasm::WASM_SEC_DATA); if (!StackPtr->getFragmentList().empty()) { if (StackPtr->getFragmentList().size() != 1) report_fatal_error("only one .stack_pointer fragment supported"); @@ -1102,6 +1146,22 @@ StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data(); } + for (MCSection &Sec : Asm) { + auto &Section = static_cast(Sec); + if (Section.getType() != wasm::WASM_SEC_DATA) + continue; + + 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); + DataSize += Segment.Data.size(); + Section.setMemoryOffset(Segment.Offset); + } + // Handle regular defined and undefined symbols. for (const MCSymbol &S : Asm.symbols()) { // Ignore unnamed temporary symbols, which aren't ever exported, imported, @@ -1164,9 +1224,6 @@ if (!WS.isDefined(/*SetUsed=*/false)) continue; - if (WS.getOffset() != 0) - report_fatal_error("data sections must contain one variable each: " + - WS.getName()); if (!WS.getSize()) report_fatal_error("data symbols must have a size set with .size: " + WS.getName()); @@ -1175,58 +1232,20 @@ if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) report_fatal_error(".size expression must be evaluatable"); - auto &DataSection = static_cast(WS.getSection()); - - if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection)) - report_fatal_error("data sections must contain at most one variable"); - - DataAlignment = std::max(DataAlignment, DataSection.getAlignment()); - - DataSegments.emplace_back(); - WasmDataSegment &Segment = DataSegments.back(); - - DataSize = alignTo(DataSize, DataSection.getAlignment()); - Segment.Offset = DataSize; - Segment.Section = &DataSection; - // For each global, prepare a corresponding wasm global holding its // address. For externals these will also be named exports. Index = NumGlobalImports + Globals.size(); + auto &DataSection = static_cast(WS.getSection()); WasmGlobal Global; Global.Type = PtrType; Global.IsMutable = false; Global.HasImport = false; - Global.InitialValue = DataSize; + Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS); Global.ImportIndex = 0; SymbolIndices[&WS] = Index; DEBUG(dbgs() << " -> global index: " << Index << "\n"); Globals.push_back(Global); - - for (const MCFragment &Frag : DataSection) { - if (Frag.hasInstructions()) - report_fatal_error("only data supported in data sections"); - - if (auto *Align = dyn_cast(&Frag)) { - if (Align->getValueSize() != 1) - report_fatal_error("only byte values supported for alignment"); - // If nops are requested, use zeros, as this is the data section. - uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue(); - uint64_t Size = std::min( - alignTo(Segment.Data.size(), Align->getAlignment()), - Segment.Data.size() + Align->getMaxBytesToEmit()); - Segment.Data.resize(Size, Value); - } else if (auto *Fill = dyn_cast(&Frag)) { - Segment.Data.insert(Segment.Data.end(), Fill->getSize(), Fill->getValue()); - } else { - const auto &DataFrag = cast(Frag); - const SmallVectorImpl &Contents = DataFrag.getContents(); - - Segment.Data.insert(Segment.Data.end(), Contents.begin(), - Contents.end()); - } - } - DataSize += Segment.Data.size(); } // If the symbol is visible outside this translation unit, export it. @@ -1297,7 +1316,8 @@ 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. Index: lib/Object/WasmObjectFile.cpp =================================================================== --- lib/Object/WasmObjectFile.cpp +++ lib/Object/WasmObjectFile.cpp @@ -396,6 +396,17 @@ 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); + dbgs() << "segment name: " << DataSegments[i].Data.Name << "\n"; + } + break; + } case wasm::WASM_STACK_POINTER: default: Ptr += Size; Index: lib/ObjectYAML/WasmYAML.cpp =================================================================== --- lib/ObjectYAML/WasmYAML.cpp +++ lib/ObjectYAML/WasmYAML.cpp @@ -60,6 +60,7 @@ 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) { Index: lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp =================================================================== --- lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -89,8 +89,6 @@ // -ffunction-sections, effectively, so that we can emit them independently. if (!TT.isOSBinFormatELF()) { this->Options.FunctionSections = true; - this->Options.DataSections = true; - this->Options.UniqueSectionNames = true; } initAsmInfo(); Index: test/CodeGen/WebAssembly/global.ll =================================================================== --- test/CodeGen/WebAssembly/global.ll +++ test/CodeGen/WebAssembly/global.ll @@ -192,7 +192,7 @@ ; Constant global. ; CHECK: .type rom,@object{{$}} -; CHECK: .section .rodata.rom, +; CHECK: .section .rodata, ; CHECK: .globl rom{{$}} ; CHECK: .p2align 4{{$}} ; CHECK: rom: @@ -205,7 +205,7 @@ ; CHECK-NEXT: .skip 8 ; CHECK-NEXT: .size array, 8 ; CHECK: .type pointer_to_array,@object -; CHECK-NEXT: .section .data.rel.ro.pointer_to_array, +; CHECK-NEXT: .section .data.rel.ro, ; CHECK-NEXT: .globl pointer_to_array ; CHECK-NEXT: .p2align 2 ; CHECK-NEXT: pointer_to_array: Index: test/CodeGen/WebAssembly/vtable.ll =================================================================== --- test/CodeGen/WebAssembly/vtable.ll +++ test/CodeGen/WebAssembly/vtable.ll @@ -36,7 +36,7 @@ @_ZTS1D = constant [3 x i8] c"1D\00" ; VTABLE: .type _ZTV1A,@object -; VTABLE-NEXT: .section .data.rel.ro._ZTV1A, +; VTABLE-NEXT: .section .data.rel.ro, ; VTABLE-NEXT: .globl _ZTV1A ; VTABLE-LABEL: _ZTV1A: ; VTABLE-NEXT: .int32 0 @@ -47,7 +47,6 @@ ; VTABLE-NEXT: .size _ZTV1A, 20 @_ZTV1A = constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*), i8* bitcast (%struct.A* (%struct.A*)* @_ZN1AD2Ev to i8*), i8* bitcast (void (%struct.A*)* @_ZN1AD0Ev to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A3fooEv to i8*)], align 4 ; VTABLE: .type _ZTV1B,@object -; VTABLE-NEXT: .section .data.rel.ro._ZTV1B, ; VTABLE-NEXT: .globl _ZTV1B ; VTABLE-LABEL: _ZTV1B: ; VTABLE-NEXT: .int32 0 @@ -58,7 +57,6 @@ ; VTABLE-NEXT: .size _ZTV1B, 20 @_ZTV1B = constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1B to i8*), i8* bitcast (%struct.A* (%struct.A*)* @_ZN1AD2Ev to i8*), i8* bitcast (void (%struct.B*)* @_ZN1BD0Ev to i8*), i8* bitcast (void (%struct.B*)* @_ZN1B3fooEv to i8*)], align 4 ; VTABLE: .type _ZTV1C,@object -; VTABLE-NEXT: .section .data.rel.ro._ZTV1C, ; VTABLE-NEXT: .globl _ZTV1C ; VTABLE-LABEL: _ZTV1C: ; VTABLE-NEXT: .int32 0 @@ -69,7 +67,6 @@ ; VTABLE-NEXT: .size _ZTV1C, 20 @_ZTV1C = constant [5 x i8*] [i8* null, i8* bitcast ({ i8*, i8*, i8* }* @_ZTI1C to i8*), i8* bitcast (%struct.A* (%struct.A*)* @_ZN1AD2Ev to i8*), i8* bitcast (void (%struct.C*)* @_ZN1CD0Ev to i8*), i8* bitcast (void (%struct.C*)* @_ZN1C3fooEv to i8*)], align 4 ; VTABLE: .type _ZTV1D,@object -; VTABLE-NEXT: .section .data.rel.ro._ZTV1D, ; VTABLE-NEXT: .globl _ZTV1D ; VTABLE-LABEL: _ZTV1D: ; VTABLE-NEXT: .int32 0 Index: test/MC/WebAssembly/array-fill.ll =================================================================== --- test/MC/WebAssembly/array-fill.ll +++ test/MC/WebAssembly/array-fill.ll @@ -9,6 +9,13 @@ @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 + Index: test/MC/WebAssembly/external-data.ll =================================================================== --- test/MC/WebAssembly/external-data.ll +++ test/MC/WebAssembly/external-data.ll @@ -7,21 +7,16 @@ @foo = global i64 7, align 4 @bar = hidden global i32* @myimport, align 4 -; CHECK: - Type: DATA -; CHECK-NEXT: Relocations: -; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: Offset: 0x00000013 -; 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: '0700000000000000' -; CHECK-NEXT: - SectionOffset: 19 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 8 -; CHECK-NEXT: Content: FFFFFFFF +; CHECK: - Type: DATA +; CHECK: Relocations: +; CHECK: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 +; CHECK: Index: 0 +; CHECK: Offset: 0x0000000E +; CHECK: Segments: +; CHECK: - SectionOffset: 6 +; CHECK: MemoryIndex: 0 +; CHECK: Offset: +; CHECK: Opcode: I32_CONST +; CHECK: Value: 0 +; CHECK: Content: 0700000000000000FFFFFFFF + Index: test/MC/WebAssembly/reloc-data.ll =================================================================== --- test/MC/WebAssembly/reloc-data.ll +++ test/MC/WebAssembly/reloc-data.ll @@ -6,40 +6,21 @@ @bar = global i64 7, align 4 @a = global i32* getelementptr (i32, i32* @foo, i32 2), align 8 @b = global i64* getelementptr (i64, i64* @bar, i64 -2), align 8 -@c = global [3 x i32*] [i32* @foo, i32* @foo, i32* @foo], align 16 -; CHECK: Format: WASM -; CHECK: Relocations [ -; CHECK-NEXT: Section (6) DATA { -; CHECK-NEXT: Relocation { -; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x13 -; CHECK-NEXT: Index: 0x0 -; CHECK-NEXT: Addend: 8 -; CHECK-NEXT: } -; CHECK-NEXT: Relocation { -; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x1C -; CHECK-NEXT: Index: 0x1 -; CHECK-NEXT: Addend: -16 -; CHECK-NEXT: } -; CHECK-NEXT: Relocation { -; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x25 -; CHECK-NEXT: Index: 0x0 -; CHECK-NEXT: Addend: 0 -; CHECK-NEXT: } -; CHECK-NEXT: Relocation { -; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x29 -; CHECK-NEXT: Index: 0x0 -; CHECK-NEXT: Addend: 0 -; CHECK-NEXT: } -; CHECK-NEXT: Relocation { -; CHECK-NEXT: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) -; CHECK-NEXT: Offset: 0x2D -; CHECK-NEXT: Index: 0x0 -; CHECK-NEXT: Addend: 0 -; CHECK-NEXT: } -; CHECK-NEXT: } -; CHECK-NEXT: ] +; CHECK: Format: WASM +; CHECK: Relocations [ +; CHECK: Section (6) DATA { +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) +; CHECK: Offset: 0xE +; CHECK: Index: 0x0 +; CHECK: Addend: 8 +; CHECK: } +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 (5) +; CHECK: Offset: 0x16 +; CHECK: Index: 0x1 +; CHECK: Addend: -16 +; CHECK: } +; CHECK: } +; CHECK: ] Index: test/MC/WebAssembly/unnamed-data.ll =================================================================== --- test/MC/WebAssembly/unnamed-data.ll +++ test/MC/WebAssembly/unnamed-data.ll @@ -41,37 +41,30 @@ ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 ; CHECK-NEXT: Index: 0 -; CHECK-NEXT: Offset: 0x0000001C +; CHECK-NEXT: Offset: 0x00000017 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32 ; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Offset: 0x00000025 +; CHECK-NEXT: Offset: 0x0000001F ; 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: 68656C6C6F00 -; CHECK-NEXT: - SectionOffset: 17 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 6 -; CHECK-NEXT: Content: 776F726C6400 -; CHECK-NEXT: - SectionOffset: 28 +; CHECK-NEXT: Content: 68656C6C6F00776F726C6400 +; CHECK-NEXT: - SectionOffset: 23 ; CHECK-NEXT: MemoryIndex: 0 ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 16 -; CHECK-NEXT: Content: '00000000' -; CHECK-NEXT: - SectionOffset: 37 -; CHECK-NEXT: MemoryIndex: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 24 -; CHECK-NEXT: Content: '06000000' +; CHECK-NEXT: Content: '000000000000000006000000' ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking ; CHECK-NEXT: DataSize: 28 ; CHECK-NEXT: DataAlignment: 8 +; CHECK-NEXT: SegmentNames: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Name: .rodata +; CHECK-NEXT: - Index: 1 +; CHECK-NEXT: Name: .data ; CHECK-NEXT: ... Index: test/tools/llvm-objdump/WebAssembly/relocations.test =================================================================== --- test/tools/llvm-objdump/WebAssembly/relocations.test +++ test/tools/llvm-objdump/WebAssembly/relocations.test @@ -5,4 +5,4 @@ @bar = hidden global i32* @foo2, align 4 ; CHECK: RELOCATION RECORDS FOR [DATA]: -; CHECK-NEXT: 00000018 R_WEBASSEMBLY_MEMORY_ADDR_I32 1+0 +; CHECK-NEXT: 0000000e R_WEBASSEMBLY_MEMORY_ADDR_I32 1+0 Index: test/tools/llvm-readobj/sections.test =================================================================== --- test/tools/llvm-readobj/sections.test +++ test/tools/llvm-readobj/sections.test @@ -543,6 +543,11 @@ 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: } +WASM-NEXT: ] WASM-NEXT: } WASM-NEXT: Section { WASM-NEXT: Type: CUSTOM (0x0) Index: tools/llvm-readobj/WasmDumper.cpp =================================================================== --- tools/llvm-readobj/WasmDumper.cpp +++ tools/llvm-readobj/WasmDumper.cpp @@ -160,6 +160,16 @@ W.printNumber("DataAlignment", LinkingData.DataAlignment); } break; + case wasm::WASM_SEC_DATA: { + ListScope Group(W, "Segments"); + for (const WasmSegment &Segment : Obj->dataSegments()) { + DictScope Group(W, "Segment"); + if (!Segment.Data.Name.empty()) + W.printString("Name", Segment.Data.Name); + W.printNumber("Size", Segment.Data.Content.size()); + } + break; + } case wasm::WASM_SEC_MEMORY: ListScope Group(W, "Memories"); for (const wasm::WasmLimits &Memory : Obj->memories()) { Index: tools/obj2yaml/wasm2yaml.cpp =================================================================== --- tools/obj2yaml/wasm2yaml.cpp +++ tools/obj2yaml/wasm2yaml.cpp @@ -70,6 +70,15 @@ 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); + } + } for (const object::SymbolRef& Sym: Obj.symbols()) { const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym); if (Symbol.Flags != 0) { @@ -234,7 +243,7 @@ } 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; Index: tools/yaml2obj/yaml2wasm.cpp =================================================================== --- tools/yaml2obj/yaml2wasm.cpp +++ tools/yaml2obj/yaml2wasm.cpp @@ -157,6 +157,17 @@ 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; }