Index: llvm/trunk/include/llvm/BinaryFormat/Wasm.h =================================================================== --- llvm/trunk/include/llvm/BinaryFormat/Wasm.h +++ llvm/trunk/include/llvm/BinaryFormat/Wasm.h @@ -250,8 +250,9 @@ // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE enum WasmSymbolType : unsigned { WASM_SYMBOL_TYPE_FUNCTION = 0x0, - WASM_SYMBOL_TYPE_DATA = 0x1, - WASM_SYMBOL_TYPE_GLOBAL = 0x2, + WASM_SYMBOL_TYPE_DATA = 0x1, + WASM_SYMBOL_TYPE_GLOBAL = 0x2, + WASM_SYMBOL_TYPE_SECTION = 0x3, }; const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; Index: llvm/trunk/include/llvm/BinaryFormat/WasmRelocs.def =================================================================== --- llvm/trunk/include/llvm/BinaryFormat/WasmRelocs.def +++ llvm/trunk/include/llvm/BinaryFormat/WasmRelocs.def @@ -11,3 +11,5 @@ WASM_RELOC(R_WEBASSEMBLY_MEMORY_ADDR_I32, 5) WASM_RELOC(R_WEBASSEMBLY_TYPE_INDEX_LEB, 6) WASM_RELOC(R_WEBASSEMBLY_GLOBAL_INDEX_LEB, 7) +WASM_RELOC(R_WEBASSEMBLY_FUNCTION_OFFSET_I32, 8) +WASM_RELOC(R_WEBASSEMBLY_SECTION_OFFSET_I32, 9) Index: llvm/trunk/include/llvm/Object/RelocVisitor.h =================================================================== --- llvm/trunk/include/llvm/Object/RelocVisitor.h +++ llvm/trunk/include/llvm/Object/RelocVisitor.h @@ -23,6 +23,7 @@ #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Object/Wasm.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include @@ -46,6 +47,8 @@ return visitCOFF(Rel, R, Value); if (isa(ObjToVisit)) return visitMachO(Rel, R, Value); + if (isa(ObjToVisit)) + return visitWasm(Rel, R, Value); HasError = true; return 0; @@ -316,6 +319,27 @@ HasError = true; return 0; } + + uint64_t visitWasm(uint32_t Rel, RelocationRef R, uint64_t Value) { + if (ObjToVisit.getArch() == Triple::wasm32) { + switch (Rel) { + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: + // For wasm section, its offset at 0 -- ignoring Value + return 0; + } + } + HasError = true; + return 0; + } }; } // end namespace object Index: llvm/trunk/include/llvm/Object/Wasm.h =================================================================== --- llvm/trunk/include/llvm/Object/Wasm.h +++ llvm/trunk/include/llvm/Object/Wasm.h @@ -53,6 +53,10 @@ return Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL; } + bool isTypeSection() const { + return Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION; + } + bool isDefined() const { return !isUndefined(); } bool isUndefined() const { @@ -206,6 +210,7 @@ bool isValidFunctionSymbol(uint32_t Index) const; bool isValidGlobalSymbol(uint32_t Index) const; bool isValidDataSymbol(uint32_t Index) const; + bool isValidSectionSymbol(uint32_t Index) const; wasm::WasmFunction &getDefinedFunction(uint32_t Index); wasm::WasmGlobal &getDefinedGlobal(uint32_t Index); Index: llvm/trunk/lib/MC/WasmObjectWriter.cpp =================================================================== --- llvm/trunk/lib/MC/WasmObjectWriter.cpp +++ llvm/trunk/lib/MC/WasmObjectWriter.cpp @@ -48,7 +48,9 @@ struct SectionBookkeeping { // Where the size of the section is written. uint64_t SizeOffset; - // Where the contents of the section starts (after the header). + // Where the section header ends (without custom section name). + uint64_t PayloadOffset; + // Where the contents of the section starts. uint64_t ContentsOffset; uint32_t Index; }; @@ -151,6 +153,8 @@ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: return true; default: return false; @@ -169,11 +173,17 @@ }; struct WasmCustomSection { + const uint32_t INVALID_INDEX = -1; + StringRef Name; - const SmallVectorImpl &Contents; + MCSectionWasm *Section; + + uint32_t OutputContentsOffset; + uint32_t OutputIndex; - WasmCustomSection(StringRef Name, const SmallVectorImpl &Contents) - : Name(Name), Contents(Contents) {} + WasmCustomSection(StringRef Name, MCSectionWasm *Section) + : Name(Name), Section(Section), OutputContentsOffset(0), + OutputIndex(INVALID_INDEX) {} }; #if !defined(NDEBUG) @@ -207,13 +217,21 @@ DenseMap WasmIndices; // Maps data symbols to the Wasm segment and offset/size with the segment. DenseMap DataLocations; + // Maps section symbols to the section. + DenseMap CustomSectionSymbols; + + // Stores output data (index, relocations, content offset) for custom + // section. + std::vector CustomSections; + // Relocations for fixing up references in the custom sections. + DenseMap> + CustomSectionsRelocations; DenseMap FunctionTypeIndices; SmallVector FunctionTypes; SmallVector Globals; SmallVector DataSegments; - std::vector CustomSections; unsigned NumFunctionImports = 0; unsigned NumGlobalImports = 0; uint32_t SectionCount = 0; @@ -245,10 +263,12 @@ WasmIndices.clear(); TableIndices.clear(); DataLocations.clear(); + CustomSectionsRelocations.clear(); FunctionTypeIndices.clear(); FunctionTypes.clear(); Globals.clear(); DataSegments.clear(); + CustomSectionSymbols.clear(); MCObjectWriter::reset(); NumFunctionImports = 0; NumGlobalImports = 0; @@ -290,7 +310,11 @@ ArrayRef SymbolInfos, ArrayRef> InitFuncs, const std::map> &Comdats); - void writeUserCustomSections(ArrayRef CustomSections); + void writeCustomSections(const MCAssembler &Asm, const MCAsmLayout &Layout); + void writeCustomRelocSections(); + void + updateCustomSectionRelocations(const SmallVector &Functions, + const MCAsmLayout &Layout); uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry); void applyRelocations(ArrayRef Relocations, @@ -319,6 +343,7 @@ // The position where the section starts, for measuring its size. Section.ContentsOffset = getStream().tell(); + Section.PayloadOffset = getStream().tell(); Section.Index = SectionCount++; } @@ -326,14 +351,21 @@ StringRef Name) { DEBUG(dbgs() << "startCustomSection " << Name << "\n"); startSection(Section, wasm::WASM_SEC_CUSTOM); + + // The position where the section header ends, for measuring its size. + Section.PayloadOffset = getStream().tell(); + // Custom sections in wasm also have a string identifier. writeString(Name); + + // The position where the custom section starts. + Section.ContentsOffset = getStream().tell(); } // Now that the section is complete and we know how big it is, patch up the // section size field at the start of the section. void WasmObjectWriter::endSection(SectionBookkeeping &Section) { - uint64_t Size = getStream().tell() - Section.ContentsOffset; + uint64_t Size = getStream().tell() - Section.PayloadOffset; if (uint32_t(Size) != Size) report_fatal_error("section size does not fit in a uint32_t"); @@ -374,8 +406,9 @@ if (FixupSection.getSectionName().startswith(".init_array")) return; - // TODO(sbc): Add support for debug sections. - if (FixupSection.getKind().isMetadata()) + // TODO: Add support for non-debug metadata sections? + if (FixupSection.getKind().isMetadata() && + !FixupSection.getSectionName().startswith(".debug_")) return; if (const MCSymbolRefExpr *RefB = Target.getSymB()) { @@ -446,21 +479,29 @@ WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); DEBUG(dbgs() << "WasmReloc: " << Rec << "\n"); - // Relocation other than R_WEBASSEMBLY_TYPE_INDEX_LEB are currently required - // to be against a named symbol. + // Relocation other than R_WEBASSEMBLY_TYPE_INDEX_LEB, + // R_WEBASSEMBLY_SECTION_OFFSET_I32 or R_WEBASSEMBLY_FUNCTION_OFFSET_I32 + // are currently required to be against a named symbol. // TODO(sbc): Add support for relocations against unnamed temporaries such // as those generated by llvm's `blockaddress`. // See: test/MC/WebAssembly/blockaddress.ll - if (SymA->getName().empty() && Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) + if (SymA->getName().empty() && + !(Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB || + Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32 || + Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32)) report_fatal_error("relocations against un-named temporaries are not yet " "supported by wasm"); - if (FixupSection.isWasmData()) + if (FixupSection.isWasmData()) { DataRelocations.push_back(Rec); - else if (FixupSection.getKind().isText()) + } else if (FixupSection.getKind().isText()) { CodeRelocations.push_back(Rec); - else + } else if (FixupSection.getKind().isMetadata()) { + assert(FixupSection.getSectionName().startswith(".debug_")); + CustomSectionsRelocations[&FixupSection].push_back(Rec); + } else { llvm_unreachable("unexpected section type"); + } } // Write X as an (unsigned) LEB value at offset Offset in Stream, padded @@ -523,6 +564,15 @@ report_fatal_error("symbol not found in wasm index space: " + RelEntry.Symbol->getName()); return WasmIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: { + const auto &Section = + static_cast(RelEntry.Symbol->getSection()); + return Section.getSectionOffset() + RelEntry.Addend; + } + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: { + const auto &Section = *CustomSectionSymbols.find(RelEntry.Symbol)->second; + return Section.getSectionOffset() + RelEntry.Addend; + } case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: { @@ -614,6 +664,8 @@ break; case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: WriteI32(Stream, Value, Offset); break; case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: @@ -851,6 +903,13 @@ endSection(Section); } +void WasmObjectWriter::writeCustomRelocSections() { + for (const auto &Sec : CustomSections) { + auto &Relocations = CustomSectionsRelocations[Sec.Section]; + writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations); + } +} + void WasmObjectWriter::writeLinkingMetaDataSection( ArrayRef SymbolInfos, ArrayRef> InitFuncs, @@ -881,6 +940,12 @@ encodeULEB128(Sym.DataRef.Size, getStream()); } break; + case wasm::WASM_SYMBOL_TYPE_SECTION: { + const uint32_t SectionIndex = + CustomSections[Sym.ElementIndex].OutputIndex; + encodeULEB128(SectionIndex, getStream()); + break; + } default: llvm_unreachable("unexpected kind"); } @@ -927,16 +992,66 @@ endSection(Section); } -void WasmObjectWriter::writeUserCustomSections( - ArrayRef CustomSections) { - for (const auto &CustomSection : CustomSections) { +void WasmObjectWriter::writeCustomSections(const MCAssembler &Asm, + const MCAsmLayout &Layout) { + for (auto &CustomSection : CustomSections) { SectionBookkeeping Section; + auto *Sec = CustomSection.Section; startCustomSection(Section, CustomSection.Name); - writeBytes(CustomSection.Contents); + + Sec->setSectionOffset(getStream().tell() - Section.ContentsOffset); + Asm.writeSectionData(Sec, Layout); + + CustomSection.OutputContentsOffset = Section.ContentsOffset; + CustomSection.OutputIndex = Section.Index; + endSection(Section); } } +void WasmObjectWriter::updateCustomSectionRelocations( + const SmallVector &Functions, const MCAsmLayout &Layout) { + std::map SectionSymbols; + for (const auto &P : CustomSectionSymbols) + SectionSymbols[P.second] = P.first; + std::map FuncSymbols; + for (const auto &FuncInfo : Functions) + FuncSymbols[&FuncInfo.Sym->getSection()] = FuncInfo.Sym; + + // Patch relocation records for R_WEBASSEMBLY_FUNCTION_OFFSET_I32 and + // R_WEBASSEMBLY_SECTION_OFFSET_I32. The Addend is stuffed the offset from + // the beginning of the function or custom section -- all such relocations + // target the function or custom section starts. + for (auto &Section : CustomSections) { + auto &Relocations = CustomSectionsRelocations[Section.Section]; + for (WasmRelocationEntry &RelEntry : Relocations) { + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: { + assert(RelEntry.hasAddend()); + auto &Section = + static_cast(RelEntry.Symbol->getSection()); + RelEntry.Addend += Layout.getSymbolOffset(*RelEntry.Symbol); + RelEntry.Symbol = FuncSymbols[&Section]; + break; + } + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: { + assert(RelEntry.hasAddend()); + auto &Section = + static_cast(RelEntry.Symbol->getSection()); + RelEntry.Addend += Layout.getSymbolOffset(*RelEntry.Symbol); + RelEntry.Symbol = SectionSymbols[&Section]; + break; + } + default: + break; + } + } + + // Apply fixups. + applyRelocations(Relocations, Section.OutputContentsOffset); + } +} + uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) { assert(Symbol.isFunction()); assert(TypeIndices.count(&Symbol)); @@ -1043,8 +1158,7 @@ for (MCSection &Sec : Asm) { auto &Section = static_cast(Sec); - if (cast(Sec).getSectionName().startswith( - ".custom_section.")) { + if (Section.getSectionName().startswith(".custom_section.")) { if (Section.getFragmentList().empty()) continue; if (Section.getFragmentList().size() != 1) @@ -1057,8 +1171,7 @@ if (!DataFrag.getFixups().empty()) report_fatal_error("fixups not supported in .custom_section section"); StringRef UserName = Section.getSectionName().substr(16); - const SmallVectorImpl &Contents = DataFrag.getContents(); - CustomSections.push_back(WasmCustomSection(UserName, Contents)); + CustomSections.emplace_back(UserName, &Section); continue; } @@ -1088,6 +1201,31 @@ } } + // Create symbols for debug/custom sections. + for (MCSection &Sec : Asm) { + auto &DebugSection = static_cast(Sec); + StringRef SectionName = DebugSection.getSectionName(); + + // TODO: Add support for non-debug metadata sections? + if (!Sec.getKind().isMetadata() || !SectionName.startswith(".debug_")) + continue; + + uint32_t ElementIndex = CustomSections.size(); + CustomSections.emplace_back(SectionName, &DebugSection); + + MCSymbolWasm *SectionSym = + cast(Ctx.getOrCreateSymbol(SectionName)); + CustomSectionSymbols[SectionSym] = &DebugSection; + + wasm::WasmSymbolInfo Info; + Info.Name = SectionSym->getName(); + Info.Kind = wasm::WASM_SYMBOL_TYPE_SECTION; + Info.Flags = 0; + Info.ElementIndex = ElementIndex; + SymbolIndices[SectionSym] = SymbolInfos.size(); + SymbolInfos.emplace_back(Info); + } + // Populate WasmIndices and DataLocations for defined symbols. for (const MCSymbol &S : Asm.symbols()) { // Ignore unnamed temporary symbols, which aren't ever exported, imported, @@ -1331,13 +1469,14 @@ writeElemSection(TableElems); writeCodeSection(Asm, Layout, Functions); writeDataSection(); - writeUserCustomSections(CustomSections); + writeCustomSections(Asm, Layout); + updateCustomSectionRelocations(Functions, Layout); writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats); writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations); writeRelocSection(DataSectionIndex, "DATA", DataRelocations); + writeCustomRelocSections(); // TODO: Translate the .comment section to the output. - // TODO: Translate debug sections to the output. } std::unique_ptr Index: llvm/trunk/lib/Object/WasmObjectFile.cpp =================================================================== --- llvm/trunk/lib/Object/WasmObjectFile.cpp +++ llvm/trunk/lib/Object/WasmObjectFile.cpp @@ -465,6 +465,14 @@ } break; + case wasm::WASM_SYMBOL_TYPE_SECTION: { + Info.ElementIndex = readVaruint32(Ptr); + // Use somewhat unique section name as symbol name. + StringRef SectionName = Sections[Info.ElementIndex].Name; + Info.Name = SectionName; + break; + } + default: return make_error("Invalid symbol type", object_error::parse_failed); @@ -573,6 +581,18 @@ object_error::parse_failed); Reloc.Addend = readVarint32(Ptr); break; + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: + if (!isValidFunctionSymbol(Reloc.Index)) + return make_error("Bad relocation function index", + object_error::parse_failed); + Reloc.Addend = readVarint32(Ptr); + break; + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: + if (!isValidSectionSymbol(Reloc.Index)) + return make_error("Bad relocation section index", + object_error::parse_failed); + Reloc.Addend = readVarint32(Ptr); + break; default: return make_error("Bad relocation type: " + Twine(Reloc.Type), @@ -584,7 +604,9 @@ // to check that. uint64_t Size = 5; if (Reloc.Type == wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 || - Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32) + Reloc.Type == wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32 || + Reloc.Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32 || + Reloc.Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32) Size = 4; if (Reloc.Offset + Size > EndOffset) return make_error("Bad relocation offset", @@ -811,6 +833,10 @@ return Index < Symbols.size() && Symbols[Index].isTypeData(); } +bool WasmObjectFile::isValidSectionSymbol(uint32_t Index) const { + return Index < Symbols.size() && Symbols[Index].isTypeSection(); +} + wasm::WasmFunction &WasmObjectFile::getDefinedFunction(uint32_t Index) { assert(isDefinedFunctionIndex(Index)); return Functions[Index - NumImportedFunctions]; @@ -991,6 +1017,8 @@ assert(Segment.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST); return Segment.Offset.Value.Int32 + Sym.Info.DataRef.Offset; } + case wasm::WASM_SYMBOL_TYPE_SECTION: + return 0; } llvm_unreachable("invalid symbol type"); } @@ -1020,6 +1048,8 @@ return SymbolRef::ST_Other; case wasm::WASM_SYMBOL_TYPE_DATA: return SymbolRef::ST_Data; + case wasm::WASM_SYMBOL_TYPE_SECTION: + return SymbolRef::ST_Debug; } llvm_unreachable("Unknown WasmSymbol::SymbolType"); @@ -1043,6 +1073,10 @@ case wasm::WASM_SYMBOL_TYPE_DATA: Ref.d.a = DataSection; break; + case wasm::WASM_SYMBOL_TYPE_SECTION: { + Ref.d.a = Sym.Info.ElementIndex; + break; + } default: llvm_unreachable("Unknown WasmSymbol::SymbolType"); } Index: llvm/trunk/lib/ObjectYAML/WasmYAML.cpp =================================================================== --- llvm/trunk/lib/ObjectYAML/WasmYAML.cpp +++ llvm/trunk/lib/ObjectYAML/WasmYAML.cpp @@ -405,6 +405,8 @@ IO.mapOptional("Offset", Info.DataRef.Offset, 0u); IO.mapRequired("Size", Info.DataRef.Size); } + } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION) { + IO.mapRequired("Section", Info.ElementIndex); } else { llvm_unreachable("unsupported symbol kind"); } @@ -439,6 +441,7 @@ ECase(FUNCTION); ECase(DATA); ECase(GLOBAL); + ECase(SECTION); #undef ECase } Index: llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp =================================================================== --- llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ llvm/trunk/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -20,9 +20,10 @@ #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCSymbolWasm.h" -#include "llvm/MC/MCWasmObjectWriter.h" #include "llvm/MC/MCValue.h" +#include "llvm/MC/MCWasmObjectWriter.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" @@ -61,6 +62,25 @@ return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX; } +static const MCSection *GetFixupSection(const MCExpr *Expr) { + if (auto SyExp = dyn_cast(Expr)) { + if (SyExp->getSymbol().isInSection()) + return &SyExp->getSymbol().getSection(); + return nullptr; + } + + if (auto BinOp = dyn_cast(Expr)) { + auto SectionLHS = GetFixupSection(BinOp->getLHS()); + auto SectionRHS = GetFixupSection(BinOp->getRHS()); + return SectionLHS == SectionRHS ? nullptr : SectionLHS; + } + + if (auto UnOp = dyn_cast(Expr)) + return GetFixupSection(UnOp->getSubExpr()); + + return nullptr; +} + unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target, const MCFixup &Fixup) const { @@ -86,6 +106,13 @@ case FK_Data_4: if (IsFunction) return wasm::R_WEBASSEMBLY_TABLE_INDEX_I32; + if (auto Section = static_cast( + GetFixupSection(Fixup.getValue()))) { + if (Section->getKind().isText()) + return wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32; + else if (!Section->isWasmData()) + return wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32; + } return wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32; case FK_Data_8: llvm_unreachable("FK_Data_8 not implemented yet"); Index: llvm/trunk/test/MC/WebAssembly/debug-info.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/debug-info.ll +++ llvm/trunk/test/MC/WebAssembly/debug-info.ll @@ -1,9 +1,169 @@ -; RUN: llc -filetype=obj %s -o - | llvm-readobj -r -s -expand-relocs +; RUN: llc -filetype=obj %s -o - | llvm-readobj -r -s | FileCheck %s + +; CHECK: Format: WASM +; CHECK-NEXT:Arch: wasm32 +; CHECK-NEXT:AddressSize: 32bit +; CHECK-NEXT:Sections [ +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: TYPE (0x1) +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: Offset: 8 +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: IMPORT (0x2) +; CHECK-NEXT: Size: 58 +; CHECK-NEXT: Offset: 18 +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: FUNCTION (0x3) +; CHECK-NEXT: Size: 2 +; CHECK-NEXT: Offset: 82 +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: ELEM (0x9) +; CHECK-NEXT: Size: 7 +; CHECK-NEXT: Offset: 90 +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CODE (0xA) +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: Offset: 103 +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: DATA (0xB) +; CHECK-NEXT: Size: 19 +; CHECK-NEXT: Offset: 113 +; CHECK-NEXT: Segments [ +; CHECK-NEXT: Segment { +; CHECK-NEXT: Name: .data.foo +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: Offset: 0 +; CHECK-NEXT: } +; CHECK-NEXT: Segment { +; CHECK-NEXT: Name: .data.ptr2 +; CHECK-NEXT: Size: 4 +; CHECK-NEXT: Offset: 4 +; CHECK-NEXT: } +; CHECK-NEXT: ] +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 121 +; CHECK-NEXT: Offset: 138 +; CHECK-NEXT: Name: .debug_str +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 84 +; CHECK-NEXT: Offset: 276 +; CHECK-NEXT: Name: .debug_abbrev +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 106 +; CHECK-NEXT: Offset: 380 +; CHECK-NEXT: Name: .debug_info +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 0 +; CHECK-NEXT: Offset: 504 +; CHECK-NEXT: Name: .debug_ranges +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 1 +; CHECK-NEXT: Offset: 524 +; CHECK-NEXT: Name: .debug_macinfo +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 42 +; CHECK-NEXT: Offset: 546 +; CHECK-NEXT: Name: .debug_pubnames +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 26 +; CHECK-NEXT: Offset: 610 +; CHECK-NEXT: Name: .debug_pubtypes +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 57 +; CHECK-NEXT: Offset: 658 +; CHECK-NEXT: Name: .debug_line +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 100 +; CHECK-NEXT: Offset: 733 +; CHECK-NEXT: Name: linking +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 9 +; CHECK-NEXT: Offset: 847 +; CHECK-NEXT: Name: reloc.DATA +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 58 +; CHECK-NEXT: Offset: 873 +; CHECK-NEXT: Name: reloc..debug_info +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 6 +; CHECK-NEXT: Offset: 955 +; CHECK-NEXT: Name: reloc..debug_pubnames +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 6 +; CHECK-NEXT: Offset: 989 +; CHECK-NEXT: Name: reloc..debug_pubtypes +; CHECK-NEXT: } +; CHECK-NEXT: Section { +; CHECK-NEXT: Type: CUSTOM (0x0) +; CHECK-NEXT: Size: 6 +; CHECK-NEXT: Offset: 1023 +; CHECK-NEXT: Name: reloc..debug_line +; CHECK-NEXT: } +; CHECK-NEXT:] +; CHECK-NEXT:Relocations [ +; CHECK-NEXT: Section (6) DATA { +; CHECK-NEXT: 0x6 R_WEBASSEMBLY_MEMORY_ADDR_I32[10] 0 +; CHECK-NEXT: 0xF R_WEBASSEMBLY_TABLE_INDEX_I32[8] +; CHECK-NEXT: } +; CHECK-NEXT: Section (9) .debug_info { +; CHECK-NEXT: 0x6 R_WEBASSEMBLY_SECTION_OFFSET_I32[1] 0 +; CHECK-NEXT: 0xC R_WEBASSEMBLY_SECTION_OFFSET_I32[0] 0 +; CHECK-NEXT: 0x12 R_WEBASSEMBLY_SECTION_OFFSET_I32[0] 55 +; CHECK-NEXT: 0x16 R_WEBASSEMBLY_SECTION_OFFSET_I32[7] 0 +; CHECK-NEXT: 0x1A R_WEBASSEMBLY_SECTION_OFFSET_I32[0] 62 +; CHECK-NEXT: 0x1E R_WEBASSEMBLY_FUNCTION_OFFSET_I32[8] 0 +; CHECK-NEXT: 0x27 R_WEBASSEMBLY_SECTION_OFFSET_I32[0] 105 +; CHECK-NEXT: 0x33 R_WEBASSEMBLY_MEMORY_ADDR_I32[9] 0 +; CHECK-NEXT: 0x3D R_WEBASSEMBLY_SECTION_OFFSET_I32[0] 109 +; CHECK-NEXT: 0x44 R_WEBASSEMBLY_SECTION_OFFSET_I32[0] 113 +; CHECK-NEXT: 0x50 R_WEBASSEMBLY_MEMORY_ADDR_I32[11] 0 +; CHECK-NEXT: 0x5B R_WEBASSEMBLY_FUNCTION_OFFSET_I32[8] 0 +; CHECK-NEXT: 0x63 R_WEBASSEMBLY_SECTION_OFFSET_I32[0] 118 +; CHECK-NEXT: } +; CHECK-NEXT: Section (12) .debug_pubnames { +; CHECK-NEXT: 0x6 R_WEBASSEMBLY_SECTION_OFFSET_I32[2] 0 +; CHECK-NEXT: } +; CHECK-NEXT: Section (13) .debug_pubtypes { +; CHECK-NEXT: 0x6 R_WEBASSEMBLY_SECTION_OFFSET_I32[2] 0 +; CHECK-NEXT: } +; CHECK-NEXT: Section (14) .debug_line { +; CHECK-NEXT: 0x2B R_WEBASSEMBLY_FUNCTION_OFFSET_I32[8] 0 +; CHECK-NEXT: } +; CHECK-NEXT:] target triple = "wasm32-unknown-unknown-wasm" -; Debug information is currently not supported. This test simply verifies that -; a valid object generated. source_filename = "test.c" @myextern = external global i32, align 4 Index: llvm/trunk/test/MC/WebAssembly/dwarfdump.ll =================================================================== --- llvm/trunk/test/MC/WebAssembly/dwarfdump.ll +++ llvm/trunk/test/MC/WebAssembly/dwarfdump.ll @@ -0,0 +1,95 @@ +; RUN: llc -filetype=obj %s -o - | llvm-dwarfdump - | FileCheck %s + +; CHECK: .debug_info contents: +; CHECK-NEXT: 0x00000000: Compile Unit: length = 0x00000066 version = 0x0004 abbr_offset = 0x0000 addr_size = 0x04 (next unit at 0x0000006a) + +; CHECK: 0x0000000b: DW_TAG_compile_unit +; CHECK-NEXT: DW_AT_producer ("clang version 6.0.0 (trunk 315924) (llvm/trunk 315960)") +; CHECK-NEXT: DW_AT_language (DW_LANG_C99) +; CHECK-NEXT: DW_AT_name ("test.c") +; CHECK-NEXT: DW_AT_stmt_list (0x00000000) +; CHECK-NEXT: DW_AT_comp_dir ("/usr/local/google/home/sbc/dev/wasm/simple") +; CHECK-NEXT: DW_AT_GNU_pubnames (true) +; CHECK-NEXT: DW_AT_low_pc (0x0000000000000002) +; CHECK-NEXT: DW_AT_high_pc (0x0000000000000004) + +; CHECK: 0x00000026: DW_TAG_variable +; CHECK-NEXT: DW_AT_name ("foo") +; CHECK-NEXT: DW_AT_type (0x00000037 "int*") +; CHECK-NEXT: DW_AT_external (true) +; CHECK-NEXT: DW_AT_decl_file ("/usr/local/google/home/sbc/dev/wasm/simple/test.c") +; CHECK-NEXT: DW_AT_decl_line (4) +; CHECK-NEXT: DW_AT_location (DW_OP_addr 0x0) + +; CHECK: 0x00000037: DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type (0x0000003c "int") + +; CHECK: 0x0000003c: DW_TAG_base_type +; CHECK-NEXT: DW_AT_name ("int") +; CHECK-NEXT: DW_AT_encoding (DW_ATE_signed) +; CHECK-NEXT: DW_AT_byte_size (0x04) + +; CHECK: 0x00000043: DW_TAG_variable +; CHECK-NEXT: DW_AT_name ("ptr2") +; CHECK-NEXT: DW_AT_type (0x00000054 "subroutine *") +; CHECK-NEXT: DW_AT_external (true) +; CHECK-NEXT: DW_AT_decl_file ("/usr/local/google/home/sbc/dev/wasm/simple/test.c") +; CHECK-NEXT: DW_AT_decl_line (5) +; CHECK-NEXT: DW_AT_location (DW_OP_addr 0x4) + +; CHECK: 0x00000054: DW_TAG_pointer_type +; CHECK-NEXT: DW_AT_type (0x00000059 "subroutine ") + +; CHECK: 0x00000059: DW_TAG_subroutine_type +; CHECK-NEXT: DW_AT_prototyped (true) + +; CHECK: 0x0000005a: DW_TAG_subprogram +; CHECK-NEXT: DW_AT_low_pc (0x0000000000000002) +; CHECK-NEXT: DW_AT_high_pc (0x0000000000000004) +; CHECK-NEXT: DW_AT_name ("f2") +; CHECK-NEXT: DW_AT_decl_file ("/usr/local/google/home/sbc/dev/wasm/simple/test.c") +; CHECK-NEXT: DW_AT_decl_line (2) +; CHECK-NEXT: DW_AT_prototyped (true) +; CHECK-NEXT: DW_AT_external (true) + +; CHECK: 0x00000069: NULL + +target triple = "wasm32-unknown-unknown-wasm" + +source_filename = "test.c" + +@myextern = external global i32, align 4 +@foo = hidden global i32* @myextern, align 4, !dbg !0 +@ptr2 = hidden global void ()* @f2, align 4, !dbg !6 + +; Function Attrs: noinline nounwind optnone +define hidden void @f2() #0 !dbg !17 { +entry: + ret void, !dbg !18 +} + +attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!13, !14, !15} +!llvm.ident = !{!16} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "foo", scope: !2, file: !3, line: 4, type: !11, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 6.0.0 (trunk 315924) (llvm/trunk 315960)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) +!3 = !DIFile(filename: "test.c", directory: "/usr/local/google/home/sbc/dev/wasm/simple") +!4 = !{} +!5 = !{!0, !6} +!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) +!7 = distinct !DIGlobalVariable(name: "ptr2", scope: !2, file: !3, line: 5, type: !8, isLocal: false, isDefinition: true) +!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 32) +!9 = !DISubroutineType(types: !10) +!10 = !{null} +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 32) +!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!13 = !{i32 2, !"Dwarf Version", i32 4} +!14 = !{i32 2, !"Debug Info Version", i32 3} +!15 = !{i32 1, !"wchar_size", i32 4} +!16 = !{!"clang version 6.0.0 (trunk 315924) (llvm/trunk 315960)"} +!17 = distinct !DISubprogram(name: "f2", scope: !3, file: !3, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !2, variables: !4) +!18 = !DILocation(line: 2, column: 16, scope: !17) Index: llvm/trunk/tools/llvm-readobj/WasmDumper.cpp =================================================================== --- llvm/trunk/tools/llvm-readobj/WasmDumper.cpp +++ llvm/trunk/tools/llvm-readobj/WasmDumper.cpp @@ -84,6 +84,8 @@ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: HasAddend = true; break; default: Index: llvm/trunk/tools/obj2yaml/wasm2yaml.cpp =================================================================== --- llvm/trunk/tools/obj2yaml/wasm2yaml.cpp +++ llvm/trunk/tools/obj2yaml/wasm2yaml.cpp @@ -106,6 +106,9 @@ case wasm::WASM_SYMBOL_TYPE_GLOBAL: Info.ElementIndex = Symbol.ElementIndex; break; + case wasm::WASM_SYMBOL_TYPE_SECTION: + Info.ElementIndex = Symbol.ElementIndex; + break; } LinkingSec->SymbolTable.emplace_back(Info); } Index: llvm/trunk/tools/yaml2obj/yaml2wasm.cpp =================================================================== --- llvm/trunk/tools/yaml2obj/yaml2wasm.cpp +++ llvm/trunk/tools/yaml2obj/yaml2wasm.cpp @@ -165,6 +165,9 @@ encodeULEB128(Info.DataRef.Size, SubSection.GetStream()); } break; + case wasm::WASM_SYMBOL_TYPE_SECTION: + encodeULEB128(Info.ElementIndex, SubSection.GetStream()); + break; default: llvm_unreachable("unexpected kind"); } @@ -424,20 +427,28 @@ int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec, uint32_t SectionIndex) { - StringRef Name; switch (Sec.Type) { case wasm::WASM_SEC_CODE: - Name = "reloc.CODE"; + writeStringRef("reloc.CODE", OS); break; case wasm::WASM_SEC_DATA: - Name = "reloc.DATA"; + writeStringRef("reloc.DATA", OS); break; + case wasm::WASM_SEC_CUSTOM: { + auto CustomSection = dyn_cast(&Sec); + if (!CustomSection->Name.startswith(".debug_")) { + llvm_unreachable("not yet implemented (only for debug sections)"); + return 1; + } + + writeStringRef(("reloc." + CustomSection->Name).str(), OS); + break; + } default: llvm_unreachable("not yet implemented"); return 1; } - writeStringRef(Name, OS); encodeULEB128(SectionIndex, OS); encodeULEB128(Sec.Relocations.size(), OS); @@ -449,6 +460,8 @@ case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: + case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32: + case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: encodeULEB128(Reloc.Addend, OS); } }