Index: llvm/trunk/include/llvm/BinaryFormat/Wasm.h =================================================================== --- llvm/trunk/include/llvm/BinaryFormat/Wasm.h +++ llvm/trunk/include/llvm/BinaryFormat/Wasm.h @@ -112,6 +112,11 @@ int64_t Addend; // A value to add to the symbol. }; +struct WasmLinkingData { + uint32_t DataSize; + uint32_t DataAlignment; +}; + enum : unsigned { WASM_SEC_CUSTOM = 0, // Custom / User-defined section WASM_SEC_TYPE = 1, // Function signature declarations @@ -175,8 +180,10 @@ // Linking metadata kinds. enum : unsigned { - WASM_STACK_POINTER = 0x1, - WASM_SYMBOL_INFO = 0x2, + WASM_STACK_POINTER = 0x1, + WASM_SYMBOL_INFO = 0x2, + WASM_DATA_SIZE = 0x3, + WASM_DATA_ALIGNMENT = 0x4, }; enum : unsigned { Index: llvm/trunk/include/llvm/Object/Wasm.h =================================================================== --- llvm/trunk/include/llvm/Object/Wasm.h +++ llvm/trunk/include/llvm/Object/Wasm.h @@ -100,6 +100,7 @@ const std::vector& memories() const { return Memories; } const std::vector& globals() const { return Globals; } const std::vector& exports() const { return Exports; } + const wasm::WasmLinkingData& linkingData() const { return LinkingData; } uint32_t getNumberOfSymbols() const { return Symbols.size(); @@ -214,6 +215,7 @@ std::vector Symbols; ArrayRef CodeSection; uint32_t StartFunction = -1; + wasm::WasmLinkingData LinkingData; StringMap SymbolMap; }; Index: llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h =================================================================== --- llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h +++ llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h @@ -154,6 +154,8 @@ } std::vector SymbolInfos; + uint32_t DataSize; + uint32_t DataAlignment; }; struct TypeSection : Section { Index: llvm/trunk/lib/MC/WasmObjectWriter.cpp =================================================================== --- llvm/trunk/lib/MC/WasmObjectWriter.cpp +++ llvm/trunk/lib/MC/WasmObjectWriter.cpp @@ -265,7 +265,8 @@ uint32_t NumFuncImports); void writeCodeRelocSection(); void writeDataRelocSection(uint64_t DataSectionHeaderSize); - void writeLinkingMetaDataSection(ArrayRef WeakSymbols, + void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment, + ArrayRef WeakSymbols, bool HasStackPointer, uint32_t StackPointerGlobal); @@ -877,11 +878,8 @@ } void WasmObjectWriter::writeLinkingMetaDataSection( - ArrayRef WeakSymbols, bool HasStackPointer, - uint32_t StackPointerGlobal) { - if (!HasStackPointer && WeakSymbols.empty()) - return; - + uint32_t DataSize, uint32_t DataAlignment, ArrayRef WeakSymbols, + bool HasStackPointer, uint32_t StackPointerGlobal) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_CUSTOM, "linking"); SectionBookkeeping SubSection; @@ -902,6 +900,16 @@ endSection(SubSection); } + if (DataSize > 0) { + startSection(SubSection, wasm::WASM_DATA_SIZE); + encodeULEB128(DataSize, getStream()); + endSection(SubSection); + + startSection(SubSection, wasm::WASM_DATA_ALIGNMENT); + encodeULEB128(DataAlignment, getStream()); + endSection(SubSection); + } + endSection(Section); } @@ -923,6 +931,7 @@ unsigned NumFuncImports = 0; unsigned NumGlobalImports = 0; SmallVector DataBytes; + uint32_t DataAlignment = 1; uint32_t StackPointerGlobal = 0; bool HasStackPointer = false; @@ -1157,6 +1166,7 @@ report_fatal_error("data sections must contain at most one variable"); DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment())); + DataAlignment = std::max(DataAlignment, DataSection.getAlignment()); DataSection.setSectionOffset(DataBytes.size()); @@ -1272,7 +1282,7 @@ writeNameSection(Functions, Imports, NumFuncImports); writeCodeRelocSection(); writeDataRelocSection(DataSectionHeaderSize); - writeLinkingMetaDataSection(WeakSymbols, HasStackPointer, StackPointerGlobal); + writeLinkingMetaDataSection(DataBytes.size(), DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal); // TODO: Translate the .comment section to the output. // TODO: Translate debug sections to the output. Index: llvm/trunk/lib/Object/WasmObjectFile.cpp =================================================================== --- llvm/trunk/lib/Object/WasmObjectFile.cpp +++ llvm/trunk/lib/Object/WasmObjectFile.cpp @@ -193,6 +193,9 @@ WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err) : ObjectFile(Binary::ID_Wasm, Buffer) { + LinkingData.DataAlignment = 0; + LinkingData.DataSize = 0; + ErrorAsOutParameter ErrAsOutParam(&Err); Header.Magic = getData().substr(0, 4); if (Header.Magic != StringRef("\0asm", 4)) { @@ -305,7 +308,7 @@ auto iter = SymbolMap.find(Symbol); if (iter == SymbolMap.end()) { return make_error( - "Invalid symbol name in linking section", + "Invalid symbol name in linking section: " + Symbol, object_error::parse_failed); } uint32_t SymIndex = iter->second; @@ -318,6 +321,12 @@ } break; } + case wasm::WASM_DATA_SIZE: + LinkingData.DataSize = readVaruint32(Ptr); + break; + case wasm::WASM_DATA_ALIGNMENT: + LinkingData.DataAlignment = readVaruint32(Ptr); + break; case wasm::WASM_STACK_POINTER: default: Ptr += Size; Index: llvm/trunk/lib/ObjectYAML/WasmYAML.cpp =================================================================== --- llvm/trunk/lib/ObjectYAML/WasmYAML.cpp +++ llvm/trunk/lib/ObjectYAML/WasmYAML.cpp @@ -56,6 +56,8 @@ static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Name", Section.Name); + IO.mapRequired("DataSize", Section.DataSize); + IO.mapRequired("DataAlignment", Section.DataAlignment); IO.mapRequired("SymbolInfo", Section.SymbolInfos); } Index: llvm/trunk/test/MC/WebAssembly/unnamed-data.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/unnamed-data.ll +++ llvm/trunk/test/MC/WebAssembly/unnamed-data.ll @@ -7,47 +7,53 @@ @b = global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str2, i32 0, i32 0), align 8 -; CHECK: - Type: GLOBAL -; CHECK: Globals: -; CHECK: - Type: I32 -; CHECK: Mutable: false -; CHECK: InitExpr: -; CHECK: Opcode: I32_CONST -; CHECK: Value: 0 -; CHECK: - Type: I32 -; CHECK: Mutable: false -; CHECK: InitExpr: -; CHECK: Opcode: I32_CONST -; CHECK: Value: 6 -; CHECK: - Type: I32 -; CHECK: Mutable: false -; CHECK: InitExpr: -; CHECK: Opcode: I32_CONST -; CHECK: Value: 16 -; CHECK: - Type: I32 -; CHECK: Mutable: false -; CHECK: InitExpr: -; CHECK: Opcode: I32_CONST -; CHECK: Value: 24 -; CHECK: - Type: EXPORT -; CHECK: Exports: -; CHECK: - Name: a -; CHECK: Kind: GLOBAL -; CHECK: Index: 2 -; CHECK: - Name: b -; CHECK: Kind: GLOBAL -; CHECK: Index: 3 -; CHECK: - Type: DATA -; CHECK: Relocations: -; CHECK: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32 -; CHECK: Index: 0 -; CHECK: Offset: 0x00000016 -; CHECK: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32 -; CHECK: Index: 1 -; CHECK: Offset: 0x0000001E -; CHECK: Segments: -; CHECK: - Index: 0 -; CHECK: Offset: -; CHECK: Opcode: I32_CONST -; CHECK: Value: 0 -; CHECK: Content: 68656C6C6F00776F726C640000000000000000000000000006000000 +; CHECK: - Type: GLOBAL +; CHECK-NEXT: Globals: +; CHECK-NEXT: - Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 0 +; CHECK-NEXT: - Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 6 +; CHECK-NEXT: - Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 16 +; CHECK-NEXT: - Type: I32 +; CHECK-NEXT: Mutable: false +; CHECK-NEXT: InitExpr: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 24 +; CHECK-NEXT: - Type: EXPORT +; CHECK-NEXT: Exports: +; CHECK-NEXT: - Name: a +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 2 +; CHECK-NEXT: - Name: b +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: Index: 3 +; CHECK-NEXT: - Type: DATA +; CHECK-NEXT: Relocations: +; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32 +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Offset: 0x00000016 +; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32 +; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Offset: 0x0000001E +; CHECK-NEXT: Segments: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 0 +; CHECK-NEXT: Content: 68656C6C6F00776F726C640000000000000000000000000006000000 +; CHECK-NEXT: - Type: CUSTOM +; CHECK-NEXT: Name: linking +; CHECK-NEXT: DataSize: 28 +; CHECK-NEXT: DataAlignment: 8 +; CHECK-NEXT: SymbolInfo: +; CHECK-NEXT: ... Index: llvm/trunk/test/MC/WebAssembly/weak-alias.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/weak-alias.ll +++ llvm/trunk/test/MC/WebAssembly/weak-alias.ll @@ -27,6 +27,8 @@ ; CHECK-NEXT: Name: foo ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking +; CHECK-NEXT: DataSize: 0 +; CHECK-NEXT: DataAlignment: 0 ; CHECK-NEXT: SymbolInfo: ; CHECK-NEXT: - Name: foo_alias ; CHECK-NEXT: Flags: 1 Index: llvm/trunk/test/MC/WebAssembly/weak.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/weak.ll +++ llvm/trunk/test/MC/WebAssembly/weak.ll @@ -26,6 +26,8 @@ ; CHECK-NEXT: Name: weak_function ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: linking +; CHECK-NEXT: DataSize: 0 +; CHECK-NEXT: DataAlignment: 0 ; CHECK-NEXT: SymbolInfo: ; CHECK-NEXT: - Name: weak_external_data ; CHECK-NEXT: Flags: 1 Index: llvm/trunk/test/ObjectYAML/wasm/weak_symbols.yaml =================================================================== --- llvm/trunk/test/ObjectYAML/wasm/weak_symbols.yaml +++ llvm/trunk/test/ObjectYAML/wasm/weak_symbols.yaml @@ -3,6 +3,19 @@ FileHeader: Version: 0x00000001 Sections: + - Type: TYPE + Signatures: + - ReturnType: I32 + ParamTypes: + - Type: FUNCTION + FunctionTypes: [ 0, 0 ] + - Type: GLOBAL + Globals: + - Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 1 - Type: EXPORT Exports: - Name: function_export @@ -10,9 +23,11 @@ Index: 1 - Name: global_export Kind: GLOBAL - Index: 2 + Index: 0 - Type: CUSTOM Name: linking + DataSize: 10 + DataAlignment: 2 SymbolInfo: - Name: function_export Flags: 1 @@ -30,9 +45,11 @@ # CHECK: Index: 1 # CHECK: - Name: global_export # CHECK: Kind: GLOBAL -# CHECK: Index: 2 +# CHECK: Index: 0 # CHECK: - Type: CUSTOM # CHECK: Name: linking +# CHECK: DataSize: 10 +# CHECK: DataAlignment: 2 # CHECK: SymbolInfo: # CHECK: - Name: function_export # CHECK: Flags: 1 Index: llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml =================================================================== --- llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml +++ llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml @@ -33,6 +33,8 @@ Index: 0x00000002 - Type: CUSTOM Name: linking + DataSize: 0 + DataAlignment: 2 SymbolInfo: - Name: weak_global_func Flags: 1 Index: llvm/trunk/tools/obj2yaml/wasm2yaml.cpp =================================================================== --- llvm/trunk/tools/obj2yaml/wasm2yaml.cpp +++ llvm/trunk/tools/obj2yaml/wasm2yaml.cpp @@ -77,6 +77,8 @@ LinkingSec->SymbolInfos.push_back(Info); } } + LinkingSec->DataSize = Obj.linkingData().DataSize; + LinkingSec->DataAlignment = Obj.linkingData().DataAlignment; CustomSec = std::move(LinkingSec); } else { CustomSec = make_unique(WasmSec.Name); Index: llvm/trunk/tools/yaml2obj/yaml2wasm.cpp =================================================================== --- llvm/trunk/tools/yaml2obj/yaml2wasm.cpp +++ llvm/trunk/tools/yaml2obj/yaml2wasm.cpp @@ -110,22 +110,52 @@ return 0; } +class SubSectionWriter { + raw_ostream &OS; + std::string OutString; + raw_string_ostream StringStream; + +public: + SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {} + + void Done() { + StringStream.flush(); + encodeULEB128(OutString.size(), OS); + OS << OutString; + OutString.clear(); + } + + raw_ostream& GetStream() { + return StringStream; + } +}; + int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) { writeStringRef(Section.Name, OS); + + SubSectionWriter SubSection(OS); + + // DATA_SIZE subsection + encodeULEB128(wasm::WASM_DATA_SIZE, OS); + encodeULEB128(Section.DataSize, SubSection.GetStream()); + SubSection.Done(); + + // DATA_ALIGNMENT subsection + encodeULEB128(wasm::WASM_DATA_ALIGNMENT, OS); + encodeULEB128(Section.DataAlignment, SubSection.GetStream()); + SubSection.Done(); + + // SYMBOL_INFO subsection if (Section.SymbolInfos.size()) { encodeULEB128(wasm::WASM_SYMBOL_INFO, OS); - std::string OutString; - raw_string_ostream StringStream(OutString); - encodeULEB128(Section.SymbolInfos.size(), StringStream); + encodeULEB128(Section.SymbolInfos.size(), SubSection.GetStream()); for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) { - writeStringRef(Info.Name, StringStream); - encodeULEB128(Info.Flags, StringStream); + writeStringRef(Info.Name, SubSection.GetStream()); + encodeULEB128(Info.Flags, SubSection.GetStream()); } - StringStream.flush(); - encodeULEB128(OutString.size(), OS); - OS << OutString; + SubSection.Done(); } return 0; } @@ -134,18 +164,16 @@ writeStringRef(Section.Name, OS); if (Section.FunctionNames.size()) { encodeULEB128(wasm::WASM_NAMES_FUNCTION, OS); - std::string OutString; - raw_string_ostream StringStream(OutString); - encodeULEB128(Section.FunctionNames.size(), StringStream); + SubSectionWriter SubSection(OS); + + encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream()); for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) { - encodeULEB128(NameEntry.Index, StringStream); - writeStringRef(NameEntry.Name, StringStream); + encodeULEB128(NameEntry.Index, SubSection.GetStream()); + writeStringRef(NameEntry.Name, SubSection.GetStream()); } - StringStream.flush(); - encodeULEB128(OutString.size(), OS); - OS << OutString; + SubSection.Done(); } return 0; }