[lld] r329717 - [WebAssembly] Add support for custom sections
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 10 09:12:49 PDT 2018
Author: sbc
Date: Tue Apr 10 09:12:49 2018
New Revision: 329717
URL: http://llvm.org/viewvc/llvm-project?rev=329717&view=rev
Log:
[WebAssembly] Add support for custom sections
Copy user-defined custom sections into the output, concatenating
sections with the same name.
Differential Revision: https://reviews.llvm.org/D45340
Added:
lld/trunk/test/wasm/Inputs/custom.ll
lld/trunk/test/wasm/custom-sections.ll
Modified:
lld/trunk/wasm/InputChunks.cpp
lld/trunk/wasm/InputChunks.h
lld/trunk/wasm/InputFiles.cpp
lld/trunk/wasm/InputFiles.h
lld/trunk/wasm/OutputSections.cpp
lld/trunk/wasm/OutputSections.h
lld/trunk/wasm/Writer.cpp
Added: lld/trunk/test/wasm/Inputs/custom.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/Inputs/custom.ll?rev=329717&view=auto
==============================================================================
--- lld/trunk/test/wasm/Inputs/custom.ll (added)
+++ lld/trunk/test/wasm/Inputs/custom.ll Tue Apr 10 09:12:49 2018
@@ -0,0 +1,6 @@
+target triple = "wasm32-unknown-unknown-wasm"
+
+!0 = !{ !"red", !"foo" }
+!1 = !{ !"green", !"bar" }
+!2 = !{ !"green", !"qux" }
+!wasm.custom_sections = !{ !0, !1, !2 }
Added: lld/trunk/test/wasm/custom-sections.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/wasm/custom-sections.ll?rev=329717&view=auto
==============================================================================
--- lld/trunk/test/wasm/custom-sections.ll (added)
+++ lld/trunk/test/wasm/custom-sections.ll Tue Apr 10 09:12:49 2018
@@ -0,0 +1,22 @@
+; RUN: llc -filetype=obj %s -o %t1.o
+; RUN: llc -filetype=obj %S/Inputs/custom.ll -o %t2.o
+; RUN: wasm-ld --check-signatures --relocatable -o %t.wasm %t1.o %t2.o
+; RUN: obj2yaml %t.wasm | FileCheck %s
+
+target triple = "wasm32-unknown-unknown-wasm"
+
+define i32 @_start() local_unnamed_addr {
+entry:
+ %retval = alloca i32, align 4
+ ret i32 0
+}
+
+!0 = !{ !"red", !"extra" }
+!wasm.custom_sections = !{ !0 }
+
+; CHECK: - Type: CUSTOM
+; CHECK-NEXT: Name: green
+; CHECK-NEXT: Payload: '05677265656E626172717578'
+; CHECK-NEXT: - Type: CUSTOM
+; CHECK-NEXT: Name: red
+; CHECK-NEXT: Payload: 037265646578747261666F6F
Modified: lld/trunk/wasm/InputChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.cpp?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.cpp (original)
+++ lld/trunk/wasm/InputChunks.cpp Tue Apr 10 09:12:49 2018
@@ -143,3 +143,13 @@ void InputFunction::setTableIndex(uint32
assert(!hasTableIndex());
TableIndex = Index;
}
+
+InputSection::InputSection(const WasmSection &S, ObjFile *F)
+ : InputChunk(F, InputChunk::Section), Section(S) {
+ assert(Section.Type == llvm::wasm::WASM_SEC_CUSTOM);
+ // TODO check LEB errors
+ unsigned Count;
+ uint64_t NameSize = llvm::decodeULEB128(Section.Content.data(), &Count);
+ uint32_t PayloadOffset = Count + NameSize;
+ Payload = Section.Content.slice(PayloadOffset);
+}
Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Tue Apr 10 09:12:49 2018
@@ -44,7 +44,7 @@ class OutputSegment;
class InputChunk {
public:
- enum Kind { DataSegment, Function, SyntheticFunction };
+ enum Kind { DataSegment, Function, SyntheticFunction, Section };
Kind kind() const { return SectionKind; }
@@ -173,6 +173,25 @@ protected:
ArrayRef<uint8_t> Body;
};
+// Represents a single Wasm Section within an input file.
+class InputSection : public InputChunk {
+public:
+ InputSection(const WasmSection &S, ObjFile *F);
+
+ StringRef getName() const override { return Section.Name; }
+ uint32_t getComdat() const override { return UINT32_MAX; }
+
+protected:
+ ArrayRef<uint8_t> data() const override { return Payload; }
+
+ // Offset within the input section. This is only zero since this chunk
+ // type represents an entire input section, not part of one.
+ uint32_t getInputSectionOffset() const override { return 0; }
+
+ const WasmSection &Section;
+ ArrayRef<uint8_t> Payload;
+};
+
} // namespace wasm
std::string toString(const wasm::InputChunk *);
Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Tue Apr 10 09:12:49 2018
@@ -153,6 +153,8 @@ void ObjFile::parse() {
CodeSection = &Section;
else if (Section.Type == WASM_SEC_DATA)
DataSection = &Section;
+ else if (Section.Type == WASM_SEC_CUSTOM)
+ CustomSections.emplace_back(make<InputSection>(Section, this));
}
TypeMap.resize(getWasmObj()->types().size());
Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Tue Apr 10 09:12:49 2018
@@ -35,6 +35,7 @@ class InputChunk;
class InputFunction;
class InputSegment;
class InputGlobal;
+class InputSection;
class InputFile {
public:
@@ -108,6 +109,7 @@ public:
std::vector<InputSegment *> Segments;
std::vector<InputFunction *> Functions;
std::vector<InputGlobal *> Globals;
+ std::vector<InputSection *> CustomSections;
ArrayRef<Symbol *> getSymbols() const { return Symbols; }
Symbol *getSymbol(uint32_t Index) const { return Symbols[Index]; }
Modified: lld/trunk/wasm/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.cpp?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.cpp (original)
+++ lld/trunk/wasm/OutputSections.cpp Tue Apr 10 09:12:49 2018
@@ -189,3 +189,38 @@ void DataSection::writeRelocations(raw_o
for (const InputChunk *C : Seg->InputSegments)
C->writeRelocations(OS);
}
+
+CustomSection::CustomSection(std::string Name,
+ ArrayRef<InputSection *> InputSections)
+ : OutputSection(WASM_SEC_CUSTOM, Name), PayloadSize(0),
+ InputSections(InputSections) {
+ raw_string_ostream OS(NameData);
+ encodeULEB128(Name.size(), OS);
+ OS << Name;
+ OS.flush();
+
+ for (InputSection *Section : InputSections) {
+ Section->OutputOffset = PayloadSize;
+ PayloadSize += Section->getSize();
+ }
+
+ createHeader(PayloadSize + NameData.size());
+}
+
+void CustomSection::writeTo(uint8_t *Buf) {
+ log("writing " + toString(*this) + " size=" + Twine(getSize()) +
+ " chunks=" + Twine(InputSections.size()));
+
+ assert(Offset);
+ Buf += Offset;
+
+ // Write section header
+ memcpy(Buf, Header.data(), Header.size());
+ Buf += Header.size();
+ memcpy(Buf, NameData.data(), NameData.size());
+ Buf += NameData.size();
+
+ // Write custom sections payload
+ parallelForEach(InputSections,
+ [&](const InputSection *Section) { Section->writeTo(Buf); });
+}
Modified: lld/trunk/wasm/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.h?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.h (original)
+++ lld/trunk/wasm/OutputSections.h Tue Apr 10 09:12:49 2018
@@ -113,6 +113,27 @@ protected:
size_t BodySize = 0;
};
+// Represents a custom section in the output file. Wasm custom sections are
+// used for storing user-defined metadata. Unlike the core sections types
+// they are identified by their string name.
+// The linker combines custom sections that have the same name by simply
+// concatenating them.
+// Note that some custom sections such as "name" and "linking" are handled
+// separately and are instead synthesized by the linker.
+class CustomSection : public OutputSection {
+public:
+ CustomSection(std::string Name, ArrayRef<InputSection *> InputSections);
+ size_t getSize() const override {
+ return Header.size() + NameData.size() + PayloadSize;
+ }
+ void writeTo(uint8_t *Buf) override;
+
+protected:
+ size_t PayloadSize;
+ ArrayRef<InputSection *> InputSections;
+ std::string NameData;
+};
+
} // namespace wasm
} // namespace lld
Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=329717&r1=329716&r2=329717&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Tue Apr 10 09:12:49 2018
@@ -20,6 +20,7 @@
#include "lld/Common/Strings.h"
#include "lld/Common/Threads.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/Object/WasmTraits.h"
#include "llvm/Support/FileOutputBuffer.h"
@@ -85,6 +86,7 @@ private:
void createElemSection();
void createCodeSection();
void createDataSection();
+ void createCustomSections();
// Custom sections
void createRelocSections();
@@ -111,6 +113,8 @@ private:
std::vector<const Symbol *> SymtabEntries;
std::vector<WasmInitEntry> InitFunctions;
+ llvm::StringMap<std::vector<InputSection *>> CustomSectionMapping;
+
// Elements that are used to construct the final output
std::string Header;
std::vector<OutputSection *> OutputSections;
@@ -295,6 +299,23 @@ void Writer::createExportSection() {
}
}
+void Writer::createCustomSections() {
+ log("createCustomSections");
+ for (ObjFile *File : Symtab->ObjectFiles)
+ for (InputSection *Section : File->CustomSections)
+ CustomSectionMapping[Section->getName()].push_back(Section);
+
+ for (auto &Pair : CustomSectionMapping) {
+ StringRef Name = Pair.first();
+ // These custom sections are known the linker and synthesized rather than
+ // blindly copied
+ if (Name == "linking" || Name == "name" || Name.startswith("reloc."))
+ continue;
+ DEBUG(dbgs() << "createCustomSection: " << Name << "\n");
+ OutputSections.push_back(make<CustomSection>(Name, Pair.second));
+ }
+}
+
void Writer::createElemSection() {
if (IndirectFunctions.empty())
return;
@@ -647,6 +668,7 @@ void Writer::createSections() {
createElemSection();
createCodeSection();
createDataSection();
+ createCustomSections();
// Custom sections
if (Config->Relocatable) {
More information about the llvm-commits
mailing list