[lld] r361233 - [WebAssembly] Refactor synthetic sections and relocation processing. NFC.
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Tue May 21 02:13:10 PDT 2019
Author: sbc
Date: Tue May 21 02:13:09 2019
New Revision: 361233
URL: http://llvm.org/viewvc/llvm-project?rev=361233&view=rev
Log:
[WebAssembly] Refactor synthetic sections and relocation processing. NFC.
Major refactor to better match the structure of the ELF linker.
- Split out relocation processing into scanRelocations
- Split out synthetic sections into their own classes.
Differential Revision: https://reviews.llvm.org/D61811
Added:
lld/trunk/wasm/Relocations.cpp (with props)
lld/trunk/wasm/Relocations.h (with props)
lld/trunk/wasm/SyntheticSections.cpp (with props)
lld/trunk/wasm/SyntheticSections.h (with props)
Modified:
lld/trunk/wasm/CMakeLists.txt
lld/trunk/wasm/InputChunks.h
lld/trunk/wasm/InputFiles.cpp
lld/trunk/wasm/OutputSections.cpp
lld/trunk/wasm/OutputSections.h
lld/trunk/wasm/Symbols.cpp
lld/trunk/wasm/Symbols.h
lld/trunk/wasm/Writer.cpp
lld/trunk/wasm/Writer.h
Modified: lld/trunk/wasm/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/CMakeLists.txt?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/CMakeLists.txt (original)
+++ lld/trunk/wasm/CMakeLists.txt Tue May 21 02:13:09 2019
@@ -13,8 +13,10 @@ add_lld_library(lldWasm
LTO.cpp
MarkLive.cpp
OutputSections.cpp
+ Relocations.cpp
SymbolTable.cpp
Symbols.cpp
+ SyntheticSections.cpp
Writer.cpp
WriterUtils.cpp
@@ -35,4 +37,4 @@ add_lld_library(lldWasm
DEPENDS
WasmOptionsTableGen
${tablegen_deps}
- )
\ No newline at end of file
+ )
Modified: lld/trunk/wasm/InputChunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.h?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.h (original)
+++ lld/trunk/wasm/InputChunks.h Tue May 21 02:13:09 2019
@@ -31,6 +31,7 @@ namespace wasm {
class ObjFile;
class OutputSegment;
+class OutputSection;
class InputChunk {
public:
@@ -207,6 +208,8 @@ public:
StringRef getDebugName() const override { return StringRef(); }
uint32_t getComdat() const override { return UINT32_MAX; }
+ OutputSection *OutputSec = nullptr;
+
protected:
ArrayRef<uint8_t> data() const override { return Section.Content; }
Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Tue May 21 02:13:09 2019
@@ -75,7 +75,10 @@ uint32_t ObjFile::calcNewIndex(const Was
assert(TypeIsUsed[Reloc.Index]);
return TypeMap[Reloc.Index];
}
- return Symbols[Reloc.Index]->getOutputSymbolIndex();
+ const Symbol *Sym = Symbols[Reloc.Index];
+ if (auto *SS = dyn_cast<SectionSymbol>(Sym))
+ Sym = SS->getOutputSectionSymbol();
+ return Sym->getOutputSymbolIndex();
}
// Relocations can contain addend for combined sections. This function takes a
@@ -395,7 +398,7 @@ Symbol *ObjFile::createDefined(const Was
case WASM_SYMBOL_TYPE_SECTION: {
InputSection *Section = CustomSectionsByIndex[Sym.Info.ElementIndex];
assert(Sym.isBindingLocal());
- return make<SectionSymbol>(Name, Flags, Section, this);
+ return make<SectionSymbol>(Flags, Section, this);
}
case WASM_SYMBOL_TYPE_EVENT: {
InputEvent *Event =
Modified: lld/trunk/wasm/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.cpp?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.cpp (original)
+++ lld/trunk/wasm/OutputSections.cpp Tue May 21 02:13:09 2019
@@ -206,6 +206,7 @@ void CustomSection::finalizeContents() {
for (InputSection *Section : InputSections) {
Section->OutputOffset = PayloadSize;
+ Section->OutputSec = this;
PayloadSize += Section->getSize();
}
@@ -241,9 +242,3 @@ void CustomSection::writeRelocations(raw
for (const InputSection *S : InputSections)
S->writeRelocations(OS);
}
-
-void RelocSection::writeBody() {
- writeUleb128(BodyOutputStream, SectionIndex, "reloc section");
- writeUleb128(BodyOutputStream, Sec->numRelocations(), "reloc count");
- Sec->writeRelocations(BodyOutputStream);
-}
Modified: lld/trunk/wasm/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.h?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.h (original)
+++ lld/trunk/wasm/OutputSections.h Tue May 21 02:13:09 2019
@@ -38,6 +38,7 @@ public:
Offset = NewOffset;
}
void createHeader(size_t BodySize);
+ virtual bool isNeeded() const { return true; }
virtual size_t getSize() const = 0;
virtual void writeTo(uint8_t *Buf) = 0;
virtual void finalizeContents() = 0;
@@ -46,54 +47,24 @@ public:
std::string Header;
uint32_t Type;
+ uint32_t SectionIndex = UINT32_MAX;
std::string Name;
+ OutputSectionSymbol *SectionSym = nullptr;
protected:
size_t Offset = 0;
};
-class SyntheticSection : public OutputSection {
-public:
- SyntheticSection(uint32_t Type, std::string Name = "")
- : OutputSection(Type, Name), BodyOutputStream(Body) {
- if (!Name.empty())
- writeStr(BodyOutputStream, Name, "section name");
- }
-
- void writeTo(uint8_t *Buf) override {
- assert(Offset);
- log("writing " + toString(*this));
- memcpy(Buf + Offset, Header.data(), Header.size());
- memcpy(Buf + Offset + Header.size(), Body.data(), Body.size());
- }
-
- size_t getSize() const override { return Header.size() + Body.size(); }
-
- virtual void writeBody() {}
-
- void finalizeContents() override {
- writeBody();
- BodyOutputStream.flush();
- createHeader(Body.size());
- }
-
- raw_ostream &getStream() { return BodyOutputStream; }
-
- std::string Body;
-
-protected:
- llvm::raw_string_ostream BodyOutputStream;
-};
-
class CodeSection : public OutputSection {
public:
explicit CodeSection(ArrayRef<InputFunction *> Functions)
: OutputSection(llvm::wasm::WASM_SEC_CODE), Functions(Functions) {}
- size_t getSize() const override { assert(BodySize); return Header.size() + BodySize; }
+ size_t getSize() const override { return Header.size() + BodySize; }
void writeTo(uint8_t *Buf) override;
uint32_t numRelocations() const override;
void writeRelocations(raw_ostream &OS) const override;
+ bool isNeeded() const override { return Functions.size() > 0; }
void finalizeContents() override;
protected:
@@ -111,6 +82,7 @@ public:
void writeTo(uint8_t *Buf) override;
uint32_t numRelocations() const override;
void writeRelocations(raw_ostream &OS) const override;
+ bool isNeeded() const override { return Segments.size() > 0; }
void finalizeContents() override;
protected:
@@ -145,19 +117,6 @@ protected:
std::string NameData;
};
-class RelocSection : public SyntheticSection {
-public:
- RelocSection(StringRef Name, OutputSection *Sec, uint32_t SectionIndex)
- : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, Name), Sec(Sec),
- SectionIndex(SectionIndex) {}
- void writeBody() override;
-
-protected:
- OutputSection* Sec;
- uint32_t SectionIndex;
-};
-
-
} // namespace wasm
} // namespace lld
Added: lld/trunk/wasm/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Relocations.cpp?rev=361233&view=auto
==============================================================================
--- lld/trunk/wasm/Relocations.cpp (added)
+++ lld/trunk/wasm/Relocations.cpp Tue May 21 02:13:09 2019
@@ -0,0 +1,86 @@
+//===- Relocations.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Relocations.h"
+
+#include "InputChunks.h"
+#include "SyntheticSections.h"
+
+using namespace llvm;
+using namespace llvm::wasm;
+
+using namespace lld;
+using namespace lld::wasm;
+
+static bool requiresGOTAccess(const Symbol *Sym) {
+ return Config->Pic && !Sym->isHidden() && !Sym->isLocal();
+}
+
+void lld::wasm::scanRelocations(InputChunk *Chunk) {
+ if (!Chunk->Live)
+ return;
+ ObjFile *File = Chunk->File;
+ ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
+ for (const WasmRelocation &Reloc : Chunk->getRelocations()) {
+ if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) {
+ // Mark target type as live
+ File->TypeMap[Reloc.Index] =
+ Out.TypeSec->registerType(Types[Reloc.Index]);
+ File->TypeIsUsed[Reloc.Index] = true;
+ continue;
+ }
+
+ // Other relocation types all have a corresponding symbol
+ Symbol *Sym = File->getSymbols()[Reloc.Index];
+
+ switch (Reloc.Type) {
+ case R_WASM_TABLE_INDEX_I32:
+ case R_WASM_TABLE_INDEX_SLEB:
+ case R_WASM_TABLE_INDEX_REL_SLEB:
+ if (requiresGOTAccess(Sym))
+ break;
+ Out.ElemSec->addEntry(cast<FunctionSymbol>(Sym));
+ break;
+ case R_WASM_GLOBAL_INDEX_LEB:
+ if (!isa<GlobalSymbol>(Sym))
+ Out.ImportSec->addGOTEntry(Sym);
+ break;
+ case R_WASM_MEMORY_ADDR_SLEB:
+ case R_WASM_MEMORY_ADDR_LEB:
+ case R_WASM_MEMORY_ADDR_REL_SLEB:
+ if (!Config->Relocatable && Sym->isUndefined() && !Sym->isWeak()) {
+ error(toString(File) + ": cannot resolve relocation of type " +
+ relocTypeToString(Reloc.Type) +
+ " against undefined (non-weak) data symbol: " + toString(*Sym));
+ }
+ break;
+ }
+
+ if (Config->Pic) {
+ switch (Reloc.Type) {
+ case R_WASM_TABLE_INDEX_SLEB:
+ case R_WASM_MEMORY_ADDR_SLEB:
+ case R_WASM_MEMORY_ADDR_LEB:
+ // Certain relocation types can't be used when building PIC output,
+ // since they would require absolute symbol addresses at link time.
+ error(toString(File) + ": relocation " + relocTypeToString(Reloc.Type) +
+ " cannot be used againt symbol " + toString(*Sym) +
+ "; recompile with -fPIC");
+ break;
+ case R_WASM_TABLE_INDEX_I32:
+ case R_WASM_MEMORY_ADDR_I32:
+ // These relocation types are only present in the data section and
+ // will be converted into code by `generateRelocationCode`. This code
+ // requires the symbols to have GOT entires.
+ if (requiresGOTAccess(Sym))
+ Out.ImportSec->addGOTEntry(Sym);
+ break;
+ }
+ }
+ }
+}
Propchange: lld/trunk/wasm/Relocations.cpp
------------------------------------------------------------------------------
svn:eol-style = LF
Added: lld/trunk/wasm/Relocations.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Relocations.h?rev=361233&view=auto
==============================================================================
--- lld/trunk/wasm/Relocations.h (added)
+++ lld/trunk/wasm/Relocations.h Tue May 21 02:13:09 2019
@@ -0,0 +1,22 @@
+//===- Relocations.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_WASM_RELOCATIONS_H
+#define LLD_WASM_RELOCATIONS_H
+
+namespace lld {
+namespace wasm {
+
+class InputChunk;
+
+void scanRelocations(InputChunk *Chunk);
+
+} // namespace wasm
+} // namespace lld
+
+#endif
Propchange: lld/trunk/wasm/Relocations.h
------------------------------------------------------------------------------
svn:eol-style = LF
Modified: lld/trunk/wasm/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.cpp?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.cpp (original)
+++ lld/trunk/wasm/Symbols.cpp Tue May 21 02:13:09 2019
@@ -12,6 +12,7 @@
#include "InputEvent.h"
#include "InputFiles.h"
#include "InputGlobal.h"
+#include "OutputSections.h"
#include "OutputSegment.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Strings.h"
@@ -41,7 +42,7 @@ WasmSymbolType Symbol::getWasmType() con
return WASM_SYMBOL_TYPE_GLOBAL;
if (isa<EventSymbol>(this))
return WASM_SYMBOL_TYPE_EVENT;
- if (isa<SectionSymbol>(this))
+ if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this))
return WASM_SYMBOL_TYPE_SECTION;
llvm_unreachable("invalid symbol kind");
}
@@ -262,17 +263,9 @@ DefinedEvent::DefinedEvent(StringRef Nam
Event ? &Event->Signature : nullptr),
Event(Event) {}
-uint32_t SectionSymbol::getOutputSectionIndex() const {
- LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n");
- assert(OutputSectionIndex != INVALID_INDEX);
- return OutputSectionIndex;
-}
-
-void SectionSymbol::setOutputSectionIndex(uint32_t Index) {
- LLVM_DEBUG(dbgs() << "setOutputSectionIndex: " << getName() << " -> " << Index
- << "\n");
- assert(Index != INVALID_INDEX);
- OutputSectionIndex = Index;
+const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
+ assert(Section->OutputSec && Section->OutputSec->SectionSym);
+ return Section->OutputSec->SectionSym;
}
void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); }
@@ -308,6 +301,8 @@ std::string lld::toString(wasm::Symbol::
return "LazyKind";
case wasm::Symbol::SectionKind:
return "SectionKind";
+ case wasm::Symbol::OutputSectionKind:
+ return "OutputSectionKind";
}
llvm_unreachable("invalid symbol kind");
}
@@ -324,3 +319,6 @@ void lld::wasm::printTraceSymbol(Symbol
message(toString(Sym->getFile()) + S + Sym->getName());
}
+
+const char *lld::wasm::DefaultModule = "env";
+const char *lld::wasm::FunctionTableName = "__indirect_function_table";
Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Tue May 21 02:13:09 2019
@@ -17,6 +17,14 @@
namespace lld {
namespace wasm {
+// Shared string constants
+
+// The default module name to use for symbol imports.
+extern const char *DefaultModule;
+
+// The name under which to import or export the wasm table.
+extern const char *FunctionTableName;
+
using llvm::wasm::WasmSymbolType;
class InputFile;
@@ -26,6 +34,7 @@ class InputFunction;
class InputGlobal;
class InputEvent;
class InputSection;
+class OutputSection;
#define INVALID_INDEX UINT32_MAX
@@ -38,6 +47,7 @@ public:
DefinedGlobalKind,
DefinedEventKind,
SectionKind,
+ OutputSectionKind,
UndefinedFunctionKind,
UndefinedDataKind,
UndefinedGlobalKind,
@@ -46,11 +56,7 @@ public:
Kind kind() const { return SymbolKind; }
- bool isDefined() const {
- return SymbolKind == DefinedFunctionKind || SymbolKind == DefinedDataKind ||
- SymbolKind == DefinedGlobalKind || SymbolKind == DefinedEventKind ||
- SymbolKind == SectionKind;
- }
+ bool isDefined() const { return !isLazy() && !isUndefined(); }
bool isUndefined() const {
return SymbolKind == UndefinedFunctionKind ||
@@ -195,21 +201,33 @@ public:
StringRef ImportModule;
};
+// Section symbols for output sections are different from those for input
+// section. These are generated by the linker and point the OutputSection
+// rather than an InputSection.
+class OutputSectionSymbol : public Symbol {
+public:
+ OutputSectionSymbol(const OutputSection *S)
+ : Symbol("", OutputSectionKind, llvm::wasm::WASM_SYMBOL_BINDING_LOCAL,
+ nullptr),
+ Section(S) {}
+
+ static bool classof(const Symbol *S) {
+ return S->kind() == OutputSectionKind;
+ }
+
+ const OutputSection *Section;
+};
+
class SectionSymbol : public Symbol {
public:
+ SectionSymbol(uint32_t Flags, const InputSection *S, InputFile *F = nullptr)
+ : Symbol("", SectionKind, Flags, F), Section(S) {}
+
static bool classof(const Symbol *S) { return S->kind() == SectionKind; }
- SectionSymbol(StringRef Name, uint32_t Flags, const InputSection *S,
- InputFile *F = nullptr)
- : Symbol(Name, SectionKind, Flags, F), Section(S) {}
+ const OutputSectionSymbol *getOutputSectionSymbol() const;
const InputSection *Section;
-
- uint32_t getOutputSectionIndex() const;
- void setOutputSectionIndex(uint32_t Index);
-
-protected:
- uint32_t OutputSectionIndex = INVALID_INDEX;
};
class DataSymbol : public Symbol {
Added: lld/trunk/wasm/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SyntheticSections.cpp?rev=361233&view=auto
==============================================================================
--- lld/trunk/wasm/SyntheticSections.cpp (added)
+++ lld/trunk/wasm/SyntheticSections.cpp Tue May 21 02:13:09 2019
@@ -0,0 +1,543 @@
+//===- SyntheticSections.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains linker-synthesized sections.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SyntheticSections.h"
+
+#include "InputChunks.h"
+#include "InputEvent.h"
+#include "InputGlobal.h"
+#include "OutputSegment.h"
+#include "SymbolTable.h"
+#include "llvm/Support/Path.h"
+
+using namespace llvm;
+using namespace llvm::wasm;
+
+using namespace lld;
+using namespace lld::wasm;
+
+OutStruct lld::wasm::Out;
+
+namespace {
+
+// Some synthetic sections (e.g. "name" and "linking") have subsections.
+// Just like the synthetic sections themselves these need to be created before
+// they can be written out (since they are preceded by their length). This
+// class is used to create subsections and then write them into the stream
+// of the parent section.
+class SubSection {
+public:
+ explicit SubSection(uint32_t Type) : Type(Type) {}
+
+ void writeTo(raw_ostream &To) {
+ OS.flush();
+ writeUleb128(To, Type, "subsection type");
+ writeUleb128(To, Body.size(), "subsection size");
+ To.write(Body.data(), Body.size());
+ }
+
+private:
+ uint32_t Type;
+ std::string Body;
+
+public:
+ raw_string_ostream OS{Body};
+};
+
+} // namespace
+
+void DylinkSection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ writeUleb128(OS, MemSize, "MemSize");
+ writeUleb128(OS, MemAlign, "MemAlign");
+ writeUleb128(OS, Out.ElemSec->numEntries(), "TableSize");
+ writeUleb128(OS, 0, "TableAlign");
+ writeUleb128(OS, Symtab->SharedFiles.size(), "Needed");
+ for (auto *SO : Symtab->SharedFiles)
+ writeStr(OS, llvm::sys::path::filename(SO->getName()), "so name");
+}
+
+uint32_t TypeSection::registerType(const WasmSignature &Sig) {
+ auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size()));
+ if (Pair.second) {
+ LLVM_DEBUG(llvm::dbgs() << "type " << toString(Sig) << "\n");
+ Types.push_back(&Sig);
+ }
+ return Pair.first->second;
+}
+
+uint32_t TypeSection::lookupType(const WasmSignature &Sig) {
+ auto It = TypeIndices.find(Sig);
+ if (It == TypeIndices.end()) {
+ error("type not found: " + toString(Sig));
+ return 0;
+ }
+ return It->second;
+}
+
+void TypeSection::writeBody() {
+ writeUleb128(BodyOutputStream, Types.size(), "type count");
+ for (const WasmSignature *Sig : Types)
+ writeSig(BodyOutputStream, *Sig);
+}
+
+uint32_t ImportSection::numImports() const {
+ uint32_t NumImports = ImportedSymbols.size() + GOTSymbols.size();
+ if (Config->ImportMemory)
+ ++NumImports;
+ if (Config->ImportTable)
+ ++NumImports;
+ return NumImports;
+}
+
+void ImportSection::addGOTEntry(Symbol *Sym) {
+ if (Sym->hasGOTIndex())
+ return;
+ Sym->setGOTIndex(NumImportedGlobals++);
+ GOTSymbols.push_back(Sym);
+}
+
+void ImportSection::addImport(Symbol *Sym) {
+ ImportedSymbols.emplace_back(Sym);
+ if (auto *F = dyn_cast<FunctionSymbol>(Sym))
+ F->setFunctionIndex(NumImportedFunctions++);
+ else if (auto *G = dyn_cast<GlobalSymbol>(Sym))
+ G->setGlobalIndex(NumImportedGlobals++);
+ else
+ cast<EventSymbol>(Sym)->setEventIndex(NumImportedEvents++);
+}
+
+void ImportSection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ writeUleb128(OS, numImports(), "import count");
+
+ if (Config->ImportMemory) {
+ WasmImport Import;
+ Import.Module = DefaultModule;
+ Import.Field = "memory";
+ Import.Kind = WASM_EXTERNAL_MEMORY;
+ Import.Memory.Flags = 0;
+ Import.Memory.Initial = Out.MemorySec->NumMemoryPages;
+ if (Out.MemorySec->MaxMemoryPages != 0 || Config->SharedMemory) {
+ Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
+ Import.Memory.Maximum = Out.MemorySec->MaxMemoryPages;
+ }
+ if (Config->SharedMemory)
+ Import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
+ writeImport(OS, Import);
+ }
+
+ if (Config->ImportTable) {
+ uint32_t TableSize = Out.ElemSec->ElemOffset + Out.ElemSec->numEntries();
+ WasmImport Import;
+ Import.Module = DefaultModule;
+ Import.Field = FunctionTableName;
+ Import.Kind = WASM_EXTERNAL_TABLE;
+ Import.Table.ElemType = WASM_TYPE_FUNCREF;
+ Import.Table.Limits = {0, TableSize, 0};
+ writeImport(OS, Import);
+ }
+
+ for (const Symbol *Sym : ImportedSymbols) {
+ WasmImport Import;
+ if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
+ Import.Field = F->ImportName;
+ Import.Module = F->ImportModule;
+ } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
+ Import.Field = G->ImportName;
+ Import.Module = G->ImportModule;
+ } else {
+ Import.Field = Sym->getName();
+ Import.Module = DefaultModule;
+ }
+
+ if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) {
+ Import.Kind = WASM_EXTERNAL_FUNCTION;
+ Import.SigIndex = Out.TypeSec->lookupType(*FunctionSym->Signature);
+ } else if (auto *GlobalSym = dyn_cast<GlobalSymbol>(Sym)) {
+ Import.Kind = WASM_EXTERNAL_GLOBAL;
+ Import.Global = *GlobalSym->getGlobalType();
+ } else {
+ auto *EventSym = cast<EventSymbol>(Sym);
+ Import.Kind = WASM_EXTERNAL_EVENT;
+ Import.Event.Attribute = EventSym->getEventType()->Attribute;
+ Import.Event.SigIndex = Out.TypeSec->lookupType(*EventSym->Signature);
+ }
+ writeImport(OS, Import);
+ }
+
+ for (const Symbol *Sym : GOTSymbols) {
+ WasmImport Import;
+ Import.Kind = WASM_EXTERNAL_GLOBAL;
+ Import.Global = {WASM_TYPE_I32, true};
+ if (isa<DataSymbol>(Sym))
+ Import.Module = "GOT.mem";
+ else
+ Import.Module = "GOT.func";
+ Import.Field = Sym->getName();
+ writeImport(OS, Import);
+ }
+}
+
+void FunctionSection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ writeUleb128(OS, InputFunctions.size(), "function count");
+ for (const InputFunction *Func : InputFunctions)
+ writeUleb128(OS, Out.TypeSec->lookupType(Func->Signature), "sig index");
+}
+
+void FunctionSection::addFunction(InputFunction *Func) {
+ if (!Func->Live)
+ return;
+ uint32_t FunctionIndex =
+ Out.ImportSec->NumImportedFunctions + InputFunctions.size();
+ InputFunctions.emplace_back(Func);
+ Func->setFunctionIndex(FunctionIndex);
+}
+
+void TableSection::writeBody() {
+ uint32_t TableSize = Out.ElemSec->ElemOffset + Out.ElemSec->numEntries();
+
+ raw_ostream &OS = BodyOutputStream;
+ writeUleb128(OS, 1, "table count");
+ WasmLimits Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize};
+ writeTableType(OS, WasmTable{WASM_TYPE_FUNCREF, Limits});
+}
+
+void MemorySection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ bool HasMax = MaxMemoryPages != 0 || Config->SharedMemory;
+ writeUleb128(OS, 1, "memory count");
+ unsigned Flags = 0;
+ if (HasMax)
+ Flags |= WASM_LIMITS_FLAG_HAS_MAX;
+ if (Config->SharedMemory)
+ Flags |= WASM_LIMITS_FLAG_IS_SHARED;
+ writeUleb128(OS, Flags, "memory limits flags");
+ writeUleb128(OS, NumMemoryPages, "initial pages");
+ if (HasMax)
+ writeUleb128(OS, MaxMemoryPages, "max pages");
+}
+
+void GlobalSection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ writeUleb128(OS, numGlobals(), "global count");
+ for (const InputGlobal *G : InputGlobals)
+ writeGlobal(OS, G->Global);
+ for (const DefinedData *Sym : DefinedFakeGlobals) {
+ WasmGlobal Global;
+ Global.Type = {WASM_TYPE_I32, false};
+ Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
+ Global.InitExpr.Value.Int32 = Sym->getVirtualAddress();
+ writeGlobal(OS, Global);
+ }
+}
+
+void GlobalSection::addGlobal(InputGlobal *Global) {
+ if (!Global->Live)
+ return;
+ uint32_t GlobalIndex =
+ Out.ImportSec->NumImportedGlobals + InputGlobals.size();
+ LLVM_DEBUG(dbgs() << "addGlobal: " << GlobalIndex << "\n");
+ Global->setGlobalIndex(GlobalIndex);
+ Out.GlobalSec->InputGlobals.push_back(Global);
+}
+
+void EventSection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ writeUleb128(OS, InputEvents.size(), "event count");
+ for (InputEvent *E : InputEvents) {
+ E->Event.Type.SigIndex = Out.TypeSec->lookupType(E->Signature);
+ writeEvent(OS, E->Event);
+ }
+}
+
+void EventSection::addEvent(InputEvent *Event) {
+ if (!Event->Live)
+ return;
+ uint32_t EventIndex = Out.ImportSec->NumImportedEvents + InputEvents.size();
+ LLVM_DEBUG(dbgs() << "addEvent: " << EventIndex << "\n");
+ Event->setEventIndex(EventIndex);
+ InputEvents.push_back(Event);
+}
+
+void ExportSection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ writeUleb128(OS, Exports.size(), "export count");
+ for (const WasmExport &Export : Exports)
+ writeExport(OS, Export);
+}
+
+void ElemSection::addEntry(FunctionSymbol *Sym) {
+ if (Sym->hasTableIndex())
+ return;
+ Sym->setTableIndex(ElemOffset + IndirectFunctions.size());
+ IndirectFunctions.emplace_back(Sym);
+}
+
+void ElemSection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ writeUleb128(OS, 1, "segment count");
+ writeUleb128(OS, 0, "table index");
+ WasmInitExpr InitExpr;
+ if (Config->Pic) {
+ InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
+ InitExpr.Value.Global = WasmSym::TableBase->getGlobalIndex();
+ } else {
+ InitExpr.Opcode = WASM_OPCODE_I32_CONST;
+ InitExpr.Value.Int32 = ElemOffset;
+ }
+ writeInitExpr(OS, InitExpr);
+ writeUleb128(OS, IndirectFunctions.size(), "elem count");
+
+ uint32_t TableIndex = ElemOffset;
+ for (const FunctionSymbol *Sym : IndirectFunctions) {
+ assert(Sym->getTableIndex() == TableIndex);
+ writeUleb128(OS, Sym->getFunctionIndex(), "function index");
+ ++TableIndex;
+ }
+}
+
+void DataCountSection::writeBody() {
+ writeUleb128(BodyOutputStream, NumSegments, "data count");
+}
+
+bool DataCountSection::isNeeded() const {
+ return NumSegments && Out.TargetFeaturesSec->Features.count("bulk-memory");
+}
+
+static uint32_t getWasmFlags(const Symbol *Sym) {
+ uint32_t Flags = 0;
+ if (Sym->isLocal())
+ Flags |= WASM_SYMBOL_BINDING_LOCAL;
+ if (Sym->isWeak())
+ Flags |= WASM_SYMBOL_BINDING_WEAK;
+ if (Sym->isHidden())
+ Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
+ if (Sym->isUndefined())
+ Flags |= WASM_SYMBOL_UNDEFINED;
+ if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
+ if (F->getName() != F->ImportName)
+ Flags |= WASM_SYMBOL_EXPLICIT_NAME;
+ } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
+ if (G->getName() != G->ImportName)
+ Flags |= WASM_SYMBOL_EXPLICIT_NAME;
+ }
+ return Flags;
+}
+
+void LinkingSection::writeBody() {
+ raw_ostream &OS = BodyOutputStream;
+
+ writeUleb128(OS, WasmMetadataVersion, "Version");
+
+ if (!SymtabEntries.empty()) {
+ SubSection Sub(WASM_SYMBOL_TABLE);
+ writeUleb128(Sub.OS, SymtabEntries.size(), "num symbols");
+
+ for (const Symbol *Sym : SymtabEntries) {
+ assert(Sym->isDefined() || Sym->isUndefined());
+ WasmSymbolType Kind = Sym->getWasmType();
+ uint32_t Flags = getWasmFlags(Sym);
+
+ writeU8(Sub.OS, Kind, "sym kind");
+ writeUleb128(Sub.OS, Flags, "sym flags");
+
+ if (auto *F = dyn_cast<FunctionSymbol>(Sym)) {
+ writeUleb128(Sub.OS, F->getFunctionIndex(), "index");
+ if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
+ writeStr(Sub.OS, Sym->getName(), "sym name");
+ } else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) {
+ writeUleb128(Sub.OS, G->getGlobalIndex(), "index");
+ if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
+ writeStr(Sub.OS, Sym->getName(), "sym name");
+ } else if (auto *E = dyn_cast<EventSymbol>(Sym)) {
+ writeUleb128(Sub.OS, E->getEventIndex(), "index");
+ if (Sym->isDefined() || (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
+ writeStr(Sub.OS, Sym->getName(), "sym name");
+ } else if (isa<DataSymbol>(Sym)) {
+ writeStr(Sub.OS, Sym->getName(), "sym name");
+ if (auto *DataSym = dyn_cast<DefinedData>(Sym)) {
+ writeUleb128(Sub.OS, DataSym->getOutputSegmentIndex(), "index");
+ writeUleb128(Sub.OS, DataSym->getOutputSegmentOffset(),
+ "data offset");
+ writeUleb128(Sub.OS, DataSym->getSize(), "data size");
+ }
+ } else {
+ auto *S = cast<OutputSectionSymbol>(Sym);
+ writeUleb128(Sub.OS, S->Section->SectionIndex, "sym section index");
+ }
+ }
+
+ Sub.writeTo(OS);
+ }
+
+ if (DataSegments.size()) {
+ SubSection Sub(WASM_SEGMENT_INFO);
+ writeUleb128(Sub.OS, DataSegments.size(), "num data segments");
+ for (const OutputSegment *S : DataSegments) {
+ writeStr(Sub.OS, S->Name, "segment name");
+ writeUleb128(Sub.OS, S->Alignment, "alignment");
+ writeUleb128(Sub.OS, 0, "flags");
+ }
+ Sub.writeTo(OS);
+ }
+
+ if (!InitFunctions.empty()) {
+ SubSection Sub(WASM_INIT_FUNCS);
+ writeUleb128(Sub.OS, InitFunctions.size(), "num init functions");
+ for (const WasmInitEntry &F : InitFunctions) {
+ writeUleb128(Sub.OS, F.Priority, "priority");
+ writeUleb128(Sub.OS, F.Sym->getOutputSymbolIndex(), "function index");
+ }
+ Sub.writeTo(OS);
+ }
+
+ struct ComdatEntry {
+ unsigned Kind;
+ uint32_t Index;
+ };
+ std::map<StringRef, std::vector<ComdatEntry>> Comdats;
+
+ for (const InputFunction *F : Out.FunctionSec->InputFunctions) {
+ StringRef Comdat = F->getComdatName();
+ if (!Comdat.empty())
+ Comdats[Comdat].emplace_back(
+ ComdatEntry{WASM_COMDAT_FUNCTION, F->getFunctionIndex()});
+ }
+ for (uint32_t I = 0; I < DataSegments.size(); ++I) {
+ const auto &InputSegments = DataSegments[I]->InputSegments;
+ if (InputSegments.empty())
+ continue;
+ StringRef Comdat = InputSegments[0]->getComdatName();
+#ifndef NDEBUG
+ for (const InputSegment *IS : InputSegments)
+ assert(IS->getComdatName() == Comdat);
+#endif
+ if (!Comdat.empty())
+ Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I});
+ }
+
+ if (!Comdats.empty()) {
+ SubSection Sub(WASM_COMDAT_INFO);
+ writeUleb128(Sub.OS, Comdats.size(), "num comdats");
+ for (const auto &C : Comdats) {
+ writeStr(Sub.OS, C.first, "comdat name");
+ writeUleb128(Sub.OS, 0, "comdat flags"); // flags for future use
+ writeUleb128(Sub.OS, C.second.size(), "num entries");
+ for (const ComdatEntry &Entry : C.second) {
+ writeU8(Sub.OS, Entry.Kind, "entry kind");
+ writeUleb128(Sub.OS, Entry.Index, "entry index");
+ }
+ }
+ Sub.writeTo(OS);
+ }
+}
+
+void LinkingSection::addToSymtab(Symbol *Sym) {
+ Sym->setOutputSymbolIndex(SymtabEntries.size());
+ SymtabEntries.emplace_back(Sym);
+}
+
+unsigned NameSection::numNames() const {
+ unsigned NumNames = Out.ImportSec->NumImportedFunctions;
+ for (const InputFunction *F : Out.FunctionSec->InputFunctions)
+ if (!F->getName().empty() || !F->getDebugName().empty())
+ ++NumNames;
+
+ return NumNames;
+}
+
+// Create the custom "name" section containing debug symbol names.
+void NameSection::writeBody() {
+ SubSection Sub(WASM_NAMES_FUNCTION);
+ writeUleb128(Sub.OS, numNames(), "name count");
+
+ // Names must appear in function index order. As it happens ImportedSymbols
+ // and InputFunctions are numbered in order with imported functions coming
+ // first.
+ for (const Symbol *S : Out.ImportSec->ImportedSymbols) {
+ if (auto *F = dyn_cast<FunctionSymbol>(S)) {
+ writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
+ writeStr(Sub.OS, toString(*S), "symbol name");
+ }
+ }
+ for (const InputFunction *F : Out.FunctionSec->InputFunctions) {
+ if (!F->getName().empty()) {
+ writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
+ if (!F->getDebugName().empty()) {
+ writeStr(Sub.OS, F->getDebugName(), "symbol name");
+ } else {
+ writeStr(Sub.OS, maybeDemangleSymbol(F->getName()), "symbol name");
+ }
+ }
+ }
+
+ Sub.writeTo(BodyOutputStream);
+}
+
+void ProducersSection::addInfo(const WasmProducerInfo &Info) {
+ for (auto &Producers :
+ {std::make_pair(&Info.Languages, &Languages),
+ std::make_pair(&Info.Tools, &Tools), std::make_pair(&Info.SDKs, &SDKs)})
+ for (auto &Producer : *Producers.first)
+ if (Producers.second->end() ==
+ llvm::find_if(*Producers.second,
+ [&](std::pair<std::string, std::string> Seen) {
+ return Seen.first == Producer.first;
+ }))
+ Producers.second->push_back(Producer);
+}
+
+void ProducersSection::writeBody() {
+ auto &OS = BodyOutputStream;
+ writeUleb128(OS, fieldCount(), "field count");
+ for (auto &Field :
+ {std::make_pair("language", Languages),
+ std::make_pair("processed-by", Tools), std::make_pair("sdk", SDKs)}) {
+ if (Field.second.empty())
+ continue;
+ writeStr(OS, Field.first, "field name");
+ writeUleb128(OS, Field.second.size(), "number of entries");
+ for (auto &Entry : Field.second) {
+ writeStr(OS, Entry.first, "producer name");
+ writeStr(OS, Entry.second, "producer version");
+ }
+ }
+}
+
+void TargetFeaturesSection::writeBody() {
+ SmallVector<std::string, 8> Emitted(Features.begin(), Features.end());
+ llvm::sort(Emitted);
+ auto &OS = BodyOutputStream;
+ writeUleb128(OS, Emitted.size(), "feature count");
+ for (auto &Feature : Emitted) {
+ writeU8(OS, WASM_FEATURE_PREFIX_USED, "feature used prefix");
+ writeStr(OS, Feature, "feature name");
+ }
+}
+
+void RelocSection::writeBody() {
+ uint32_t Count = Sec->numRelocations();
+ assert(Sec->SectionIndex != UINT32_MAX);
+ writeUleb128(BodyOutputStream, Sec->SectionIndex, "reloc section");
+ writeUleb128(BodyOutputStream, Count, "reloc count");
+ Sec->writeRelocations(BodyOutputStream);
+}
Propchange: lld/trunk/wasm/SyntheticSections.cpp
------------------------------------------------------------------------------
svn:eol-style = LF
Added: lld/trunk/wasm/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SyntheticSections.h?rev=361233&view=auto
==============================================================================
--- lld/trunk/wasm/SyntheticSections.h (added)
+++ lld/trunk/wasm/SyntheticSections.h Tue May 21 02:13:09 2019
@@ -0,0 +1,323 @@
+//===- SyntheticSection.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Synthetic sections represent chunks of linker-created data. If you
+// need to create a chunk of data that to be included in some section
+// in the result, you probably want to create that as a synthetic section.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_WASM_SYNTHETIC_SECTIONS_H
+#define LLD_WASM_SYNTHETIC_SECTIONS_H
+
+#include "OutputSections.h"
+
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Object/WasmTraits.h"
+
+#define DEBUG_TYPE "lld"
+
+namespace lld {
+namespace wasm {
+
+// An init entry to be written to either the synthetic init func or the
+// linking metadata.
+struct WasmInitEntry {
+ const FunctionSymbol *Sym;
+ uint32_t Priority;
+};
+
+class SyntheticSection : public OutputSection {
+public:
+ SyntheticSection(uint32_t Type, std::string Name = "")
+ : OutputSection(Type, Name), BodyOutputStream(Body) {
+ if (!Name.empty())
+ writeStr(BodyOutputStream, Name, "section name");
+ }
+
+ void writeTo(uint8_t *Buf) override {
+ assert(Offset);
+ log("writing " + toString(*this));
+ memcpy(Buf + Offset, Header.data(), Header.size());
+ memcpy(Buf + Offset + Header.size(), Body.data(), Body.size());
+ }
+
+ size_t getSize() const override { return Header.size() + Body.size(); }
+
+ virtual void writeBody() {}
+
+ void finalizeContents() override {
+ writeBody();
+ BodyOutputStream.flush();
+ createHeader(Body.size());
+ }
+
+ raw_ostream &getStream() { return BodyOutputStream; }
+
+ std::string Body;
+
+protected:
+ llvm::raw_string_ostream BodyOutputStream;
+};
+
+// Create the custom "dylink" section containing information for the dynamic
+// linker.
+// See
+// https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
+class DylinkSection : public SyntheticSection {
+public:
+ DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink") {}
+ bool isNeeded() const override { return Config->Pic; }
+ void writeBody() override;
+
+ uint32_t MemAlign = 0;
+ uint32_t MemSize = 0;
+};
+
+class TypeSection : public SyntheticSection {
+public:
+ TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE) {}
+
+ bool isNeeded() const override { return Types.size() > 0; };
+ void writeBody() override;
+ uint32_t registerType(const WasmSignature &Sig);
+ uint32_t lookupType(const WasmSignature &Sig);
+
+protected:
+ std::vector<const WasmSignature *> Types;
+ llvm::DenseMap<WasmSignature, int32_t> TypeIndices;
+};
+
+class ImportSection : public SyntheticSection {
+public:
+ ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {}
+ bool isNeeded() const override { return numImports() > 0; }
+ void writeBody() override;
+ void addImport(Symbol *Sym);
+ void addGOTEntry(Symbol *Sym);
+ uint32_t numImports() const;
+
+ unsigned NumImportedGlobals = 0;
+ unsigned NumImportedFunctions = 0;
+ unsigned NumImportedEvents = 0;
+ std::vector<const Symbol *> ImportedSymbols;
+
+protected:
+ std::vector<const Symbol *> GOTSymbols;
+};
+
+class FunctionSection : public SyntheticSection {
+public:
+ FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION) {}
+
+ bool isNeeded() const override { return InputFunctions.size() > 0; };
+ void writeBody() override;
+ void addFunction(InputFunction *Func);
+
+ std::vector<InputFunction *> InputFunctions;
+
+protected:
+};
+
+class MemorySection : public SyntheticSection {
+public:
+ MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {}
+
+ bool isNeeded() const override { return !Config->ImportMemory; }
+ void writeBody() override;
+
+ uint32_t NumMemoryPages = 0;
+ uint32_t MaxMemoryPages = 0;
+};
+
+class TableSection : public SyntheticSection {
+public:
+ TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {}
+
+ bool isNeeded() const override {
+ // Always output a table section (or table import), even if there are no
+ // indirect calls. There are two reasons for this:
+ // 1. For executables it is useful to have an empty table slot at 0
+ // which can be filled with a null function call handler.
+ // 2. If we don't do this, any program that contains a call_indirect but
+ // no address-taken function will fail at validation time since it is
+ // a validation error to include a call_indirect instruction if there
+ // is not table.
+ return !Config->ImportTable;
+ }
+
+ void writeBody() override;
+};
+
+class GlobalSection : public SyntheticSection {
+public:
+ GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {}
+ uint32_t numGlobals() const {
+ return InputGlobals.size() + DefinedFakeGlobals.size();
+ }
+ bool isNeeded() const override { return numGlobals() > 0; }
+ void writeBody() override;
+ void addGlobal(InputGlobal *Global);
+
+ std::vector<const DefinedData *> DefinedFakeGlobals;
+ std::vector<InputGlobal *> InputGlobals;
+};
+
+// The event section contains a list of declared wasm events associated with the
+// module. Currently the only supported event kind is exceptions. A single event
+// entry represents a single event with an event tag. All C++ exceptions are
+// represented by a single event. An event entry in this section contains
+// information on what kind of event it is (e.g. exception) and the type of
+// values contained in a single event object. (In wasm, an event can contain
+// multiple values of primitive types. But for C++ exceptions, we just throw a
+// pointer which is an i32 value (for wasm32 architecture), so the signature of
+// C++ exception is (i32)->(void), because all event types are assumed to have
+// void return type to share WasmSignature with functions.)
+class EventSection : public SyntheticSection {
+public:
+ EventSection() : SyntheticSection(llvm::wasm::WASM_SEC_EVENT) {}
+ void writeBody() override;
+ bool isNeeded() const override { return InputEvents.size() > 0; }
+ void addEvent(InputEvent *Event);
+
+ std::vector<InputEvent *> InputEvents;
+};
+
+class ExportSection : public SyntheticSection {
+public:
+ ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT) {}
+ bool isNeeded() const override { return Exports.size() > 0; }
+ void writeBody() override;
+
+ std::vector<llvm::wasm::WasmExport> Exports;
+};
+
+class ElemSection : public SyntheticSection {
+public:
+ ElemSection(uint32_t Offset)
+ : SyntheticSection(llvm::wasm::WASM_SEC_ELEM), ElemOffset(Offset) {}
+ bool isNeeded() const override { return IndirectFunctions.size() > 0; };
+ void writeBody() override;
+ void addEntry(FunctionSymbol *Sym);
+ uint32_t numEntries() const { return IndirectFunctions.size(); }
+ uint32_t ElemOffset;
+
+protected:
+ std::vector<const FunctionSymbol *> IndirectFunctions;
+};
+
+class DataCountSection : public SyntheticSection {
+public:
+ DataCountSection(uint32_t NumSegments)
+ : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),
+ NumSegments(NumSegments) {}
+ bool isNeeded() const override;
+ void writeBody() override;
+
+protected:
+ uint32_t NumSegments;
+};
+
+// Create the custom "linking" section containing linker metadata.
+// This is only created when relocatable output is requested.
+class LinkingSection : public SyntheticSection {
+public:
+ LinkingSection(const std::vector<WasmInitEntry> &InitFunctions,
+ const std::vector<OutputSegment *> &DataSegments)
+ : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"),
+ InitFunctions(InitFunctions), DataSegments(DataSegments) {}
+ bool isNeeded() const override { return Config->Relocatable; }
+ void writeBody() override;
+ void addToSymtab(Symbol *Sym);
+
+protected:
+ std::vector<const Symbol *> SymtabEntries;
+ llvm::StringMap<uint32_t> SectionSymbolIndices;
+ const std::vector<WasmInitEntry> &InitFunctions;
+ const std::vector<OutputSegment *> &DataSegments;
+};
+
+// Create the custom "name" section containing debug symbol names.
+class NameSection : public SyntheticSection {
+public:
+ NameSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name") {}
+ bool isNeeded() const override {
+ return !Config->StripDebug && !Config->StripAll && numNames() > 0;
+ }
+ void writeBody() override;
+ unsigned numNames() const;
+};
+
+class ProducersSection : public SyntheticSection {
+public:
+ ProducersSection()
+ : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "producers") {}
+ bool isNeeded() const override {
+ return !Config->StripAll && fieldCount() > 0;
+ }
+ void writeBody() override;
+ void addInfo(const llvm::wasm::WasmProducerInfo &Info);
+
+protected:
+ int fieldCount() const {
+ return int(!Languages.empty()) + int(!Tools.empty()) + int(!SDKs.empty());
+ }
+ SmallVector<std::pair<std::string, std::string>, 8> Languages;
+ SmallVector<std::pair<std::string, std::string>, 8> Tools;
+ SmallVector<std::pair<std::string, std::string>, 8> SDKs;
+};
+
+class TargetFeaturesSection : public SyntheticSection {
+public:
+ TargetFeaturesSection()
+ : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "target_features") {}
+ bool isNeeded() const override {
+ return !Config->StripAll && Features.size() > 0;
+ }
+ void writeBody() override;
+
+ llvm::SmallSet<std::string, 8> Features;
+};
+
+class RelocSection : public SyntheticSection {
+public:
+ RelocSection(StringRef Name, OutputSection *Sec)
+ : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, Name), Sec(Sec) {}
+ void writeBody() override;
+ bool isNeeded() const override { return Sec->numRelocations() > 0; };
+
+protected:
+ OutputSection *Sec;
+};
+
+// Linker generated output sections
+struct OutStruct {
+ DylinkSection *DylinkSec;
+ TypeSection *TypeSec;
+ FunctionSection *FunctionSec;
+ ImportSection *ImportSec;
+ TableSection *TableSec;
+ MemorySection *MemorySec;
+ GlobalSection *GlobalSec;
+ EventSection *EventSec;
+ ExportSection *ExportSec;
+ ElemSection *ElemSec;
+ DataCountSection *DataCountSec;
+ LinkingSection *LinkingSec;
+ NameSection *NameSec;
+ ProducersSection *ProducersSec;
+ TargetFeaturesSection *TargetFeaturesSec;
+};
+
+extern OutStruct Out;
+
+} // namespace wasm
+} // namespace lld
+
+#endif
Propchange: lld/trunk/wasm/SyntheticSections.h
------------------------------------------------------------------------------
svn:eol-style = LF
Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Tue May 21 02:13:09 2019
@@ -13,7 +13,9 @@
#include "InputGlobal.h"
#include "OutputSections.h"
#include "OutputSegment.h"
+#include "Relocations.h"
#include "SymbolTable.h"
+#include "SyntheticSections.h"
#include "WriterUtils.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
@@ -29,7 +31,6 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/LEB128.h"
-#include "llvm/Support/Path.h"
#include <cstdarg>
#include <map>
@@ -42,18 +43,9 @@ using namespace lld;
using namespace lld::wasm;
static constexpr int StackAlignment = 16;
-static constexpr const char *FunctionTableName = "__indirect_function_table";
-const char *lld::wasm::DefaultModule = "env";
namespace {
-// An init entry to be written to either the synthetic init func or the
-// linking metadata.
-struct WasmInitEntry {
- const FunctionSymbol *Sym;
- uint32_t Priority;
-};
-
// The writer writes a SymbolTable result to a file.
class Writer {
public:
@@ -62,81 +54,40 @@ public:
private:
void openFile();
- uint32_t lookupType(const WasmSignature &Sig);
- uint32_t registerType(const WasmSignature &Sig);
-
void createApplyRelocationsFunction();
void createCallCtorsFunction();
- void calculateInitFunctions();
- void processRelocations(InputChunk *Chunk);
void assignIndexes();
- void calculateTargetFeatures();
+ void populateSymtab();
+ void populateProducers();
+ void populateTargetFeatures();
+ void calculateInitFunctions();
void calculateImports();
void calculateExports();
void calculateCustomSections();
- void assignSymtab();
void calculateTypes();
void createOutputSegments();
void layoutMemory();
void createHeader();
- void createSections();
- SyntheticSection *createSyntheticSection(uint32_t Type, StringRef Name = "");
- // Builtin sections
- void createTypeSection();
- void createFunctionSection();
- void createTableSection();
- void createGlobalSection();
- void createEventSection();
- void createExportSection();
- void createImportSection();
- void createMemorySection();
- void createElemSection();
- void createDataCountSection();
- void createCodeSection();
- void createDataSection();
+ void addSection(OutputSection *Sec);
+
+ void addSections();
void createCustomSections();
+ void createSyntheticSections();
+ void finalizeSections();
// Custom sections
- void createDylinkSection();
void createRelocSections();
- void createLinkingSection();
- void createNameSection();
- void createProducersSection();
- void createTargetFeaturesSection();
void writeHeader();
void writeSections();
uint64_t FileSize = 0;
uint32_t TableBase = 0;
- uint32_t NumMemoryPages = 0;
- uint32_t MaxMemoryPages = 0;
- // Memory size and aligment. Written to the "dylink" section
- // when build with -shared or -pie.
- uint32_t MemAlign = 0;
- uint32_t MemSize = 0;
-
- std::vector<const WasmSignature *> Types;
- DenseMap<WasmSignature, int32_t> TypeIndices;
- std::vector<const Symbol *> ImportedSymbols;
- std::vector<const Symbol *> GOTSymbols;
- unsigned NumImportedFunctions = 0;
- unsigned NumImportedGlobals = 0;
- unsigned NumImportedEvents = 0;
- std::vector<WasmExport> Exports;
- std::vector<const DefinedData *> DefinedFakeGlobals;
- std::vector<InputGlobal *> InputGlobals;
- std::vector<InputFunction *> InputFunctions;
- std::vector<InputEvent *> InputEvents;
- std::vector<const FunctionSymbol *> IndirectFunctions;
- std::vector<const Symbol *> SymtabEntries;
- std::vector<WasmInitEntry> InitFunctions;
+ std::vector<WasmInitEntry> InitFunctions;
llvm::StringMap<std::vector<InputSection *>> CustomSectionMapping;
- llvm::StringMap<SectionSymbol *> CustomSectionSymbols;
- llvm::SmallSet<std::string, 8> TargetFeatures;
// Elements that are used to construct the final output
std::string Header;
@@ -150,210 +101,6 @@ private:
} // anonymous namespace
-void Writer::createImportSection() {
- uint32_t NumImports = ImportedSymbols.size() + GOTSymbols.size();
- if (Config->ImportMemory)
- ++NumImports;
- if (Config->ImportTable)
- ++NumImports;
-
- if (NumImports == 0)
- return;
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_IMPORT);
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, NumImports, "import count");
-
- if (Config->ImportMemory) {
- WasmImport Import;
- Import.Module = DefaultModule;
- Import.Field = "memory";
- Import.Kind = WASM_EXTERNAL_MEMORY;
- Import.Memory.Flags = 0;
- Import.Memory.Initial = NumMemoryPages;
- if (MaxMemoryPages != 0 || Config->SharedMemory) {
- Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
- Import.Memory.Maximum = MaxMemoryPages;
- }
- if (Config->SharedMemory)
- Import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
- writeImport(OS, Import);
- }
-
- if (Config->ImportTable) {
- uint32_t TableSize = TableBase + IndirectFunctions.size();
- WasmImport Import;
- Import.Module = DefaultModule;
- Import.Field = FunctionTableName;
- Import.Kind = WASM_EXTERNAL_TABLE;
- Import.Table.ElemType = WASM_TYPE_FUNCREF;
- Import.Table.Limits = {0, TableSize, 0};
- writeImport(OS, Import);
- }
-
- for (const Symbol *Sym : ImportedSymbols) {
- WasmImport Import;
- if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
- Import.Field = F->ImportName;
- Import.Module = F->ImportModule;
- } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
- Import.Field = G->ImportName;
- Import.Module = G->ImportModule;
- } else {
- Import.Field = Sym->getName();
- Import.Module = DefaultModule;
- }
-
- if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) {
- Import.Kind = WASM_EXTERNAL_FUNCTION;
- Import.SigIndex = lookupType(*FunctionSym->Signature);
- } else if (auto *GlobalSym = dyn_cast<GlobalSymbol>(Sym)) {
- Import.Kind = WASM_EXTERNAL_GLOBAL;
- Import.Global = *GlobalSym->getGlobalType();
- } else {
- auto *EventSym = cast<EventSymbol>(Sym);
- Import.Kind = WASM_EXTERNAL_EVENT;
- Import.Event.Attribute = EventSym->getEventType()->Attribute;
- Import.Event.SigIndex = lookupType(*EventSym->Signature);
- }
- writeImport(OS, Import);
- }
-
- for (const Symbol *Sym : GOTSymbols) {
- WasmImport Import;
- Import.Kind = WASM_EXTERNAL_GLOBAL;
- Import.Global = {WASM_TYPE_I32, true};
- if (isa<DataSymbol>(Sym))
- Import.Module = "GOT.mem";
- else
- Import.Module = "GOT.func";
- Import.Field = Sym->getName();
- writeImport(OS, Import);
- }
-}
-
-void Writer::createTypeSection() {
- if (!Types.size())
- return;
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_TYPE);
- raw_ostream &OS = Section->getStream();
- writeUleb128(OS, Types.size(), "type count");
- for (const WasmSignature *Sig : Types)
- writeSig(OS, *Sig);
-}
-
-void Writer::createFunctionSection() {
- if (InputFunctions.empty())
- return;
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION);
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, InputFunctions.size(), "function count");
- for (const InputFunction *Func : InputFunctions)
- writeUleb128(OS, lookupType(Func->Signature), "sig index");
-}
-
-void Writer::createMemorySection() {
- if (Config->ImportMemory)
- return;
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY);
- raw_ostream &OS = Section->getStream();
-
- bool HasMax = MaxMemoryPages != 0 || Config->SharedMemory;
- writeUleb128(OS, 1, "memory count");
- unsigned Flags = 0;
- if (HasMax)
- Flags |= WASM_LIMITS_FLAG_HAS_MAX;
- if (Config->SharedMemory)
- Flags |= WASM_LIMITS_FLAG_IS_SHARED;
- writeUleb128(OS, Flags, "memory limits flags");
- writeUleb128(OS, NumMemoryPages, "initial pages");
- if (HasMax)
- writeUleb128(OS, MaxMemoryPages, "max pages");
-}
-
-void Writer::createGlobalSection() {
- unsigned NumGlobals = InputGlobals.size() + DefinedFakeGlobals.size();
- if (NumGlobals == 0)
- return;
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL);
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, NumGlobals, "global count");
- for (const InputGlobal *G : InputGlobals)
- writeGlobal(OS, G->Global);
- for (const DefinedData *Sym : DefinedFakeGlobals) {
- WasmGlobal Global;
- Global.Type = {WASM_TYPE_I32, false};
- Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
- Global.InitExpr.Value.Int32 = Sym->getVirtualAddress();
- writeGlobal(OS, Global);
- }
-}
-
-// The event section contains a list of declared wasm events associated with the
-// module. Currently the only supported event kind is exceptions. A single event
-// entry represents a single event with an event tag. All C++ exceptions are
-// represented by a single event. An event entry in this section contains
-// information on what kind of event it is (e.g. exception) and the type of
-// values contained in a single event object. (In wasm, an event can contain
-// multiple values of primitive types. But for C++ exceptions, we just throw a
-// pointer which is an i32 value (for wasm32 architecture), so the signature of
-// C++ exception is (i32)->(void), because all event types are assumed to have
-// void return type to share WasmSignature with functions.)
-void Writer::createEventSection() {
- unsigned NumEvents = InputEvents.size();
- if (NumEvents == 0)
- return;
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_EVENT);
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, NumEvents, "event count");
- for (InputEvent *E : InputEvents) {
- E->Event.Type.SigIndex = lookupType(E->Signature);
- writeEvent(OS, E->Event);
- }
-}
-
-void Writer::createTableSection() {
- if (Config->ImportTable)
- return;
-
- // Always output a table section (or table import), even if there are no
- // indirect calls. There are two reasons for this:
- // 1. For executables it is useful to have an empty table slot at 0
- // which can be filled with a null function call handler.
- // 2. If we don't do this, any program that contains a call_indirect but
- // no address-taken function will fail at validation time since it is
- // a validation error to include a call_indirect instruction if there
- // is not table.
- uint32_t TableSize = TableBase + IndirectFunctions.size();
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE);
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, 1, "table count");
- WasmLimits Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize};
- writeTableType(OS, WasmTable{WASM_TYPE_FUNCREF, Limits});
-}
-
-void Writer::createExportSection() {
- if (!Exports.size())
- return;
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_EXPORT);
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, Exports.size(), "export count");
- for (const WasmExport &Export : Exports)
- writeExport(OS, Export);
-}
-
void Writer::calculateCustomSections() {
log("calculateCustomSections");
bool StripDebug = Config->StripDebug || Config->StripAll;
@@ -377,75 +124,18 @@ void Writer::createCustomSections() {
log("createCustomSections");
for (auto &Pair : CustomSectionMapping) {
StringRef Name = Pair.first();
-
- auto P = CustomSectionSymbols.find(Name);
- if (P != CustomSectionSymbols.end()) {
- uint32_t SectionIndex = OutputSections.size();
- P->second->setOutputSectionIndex(SectionIndex);
- }
-
LLVM_DEBUG(dbgs() << "createCustomSection: " << Name << "\n");
- OutputSections.push_back(make<CustomSection>(Name, Pair.second));
- }
-}
-void Writer::createElemSection() {
- if (IndirectFunctions.empty())
- return;
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_ELEM);
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, 1, "segment count");
- writeUleb128(OS, 0, "table index");
- WasmInitExpr InitExpr;
- if (Config->Pic) {
- InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
- InitExpr.Value.Global = WasmSym::TableBase->getGlobalIndex();
- } else {
- InitExpr.Opcode = WASM_OPCODE_I32_CONST;
- InitExpr.Value.Int32 = TableBase;
- }
- writeInitExpr(OS, InitExpr);
- writeUleb128(OS, IndirectFunctions.size(), "elem count");
-
- uint32_t TableIndex = TableBase;
- for (const FunctionSymbol *Sym : IndirectFunctions) {
- assert(Sym->getTableIndex() == TableIndex);
- writeUleb128(OS, Sym->getFunctionIndex(), "function index");
- ++TableIndex;
+ OutputSection *Sec = make<CustomSection>(Name, Pair.second);
+ if (Config->Relocatable) {
+ auto *Sym = make<OutputSectionSymbol>(Sec);
+ Out.LinkingSec->addToSymtab(Sym);
+ Sec->SectionSym = Sym;
+ }
+ addSection(Sec);
}
}
-void Writer::createDataCountSection() {
- if (!Segments.size() || !TargetFeatures.count("bulk-memory"))
- return;
-
- log("createDataCountSection");
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_DATACOUNT);
- raw_ostream &OS = Section->getStream();
- writeUleb128(OS, Segments.size(), "data count");
-}
-
-void Writer::createCodeSection() {
- if (InputFunctions.empty())
- return;
-
- log("createCodeSection");
-
- auto Section = make<CodeSection>(InputFunctions);
- OutputSections.push_back(Section);
-}
-
-void Writer::createDataSection() {
- if (!Segments.size())
- return;
-
- log("createDataSection");
- auto Section = make<DataSection>(Segments);
- OutputSections.push_back(Section);
-}
-
// Create relocations sections in the final output.
// These are only created when relocatable output is requested.
void Writer::createRelocSections() {
@@ -453,293 +143,33 @@ void Writer::createRelocSections() {
// Don't use iterator here since we are adding to OutputSection
size_t OrigSize = OutputSections.size();
for (size_t I = 0; I < OrigSize; I++) {
- OutputSection *OSec = OutputSections[I];
- uint32_t Count = OSec->numRelocations();
+ LLVM_DEBUG(dbgs() << "check section " << I << "\n");
+ OutputSection *Sec = OutputSections[I];
+
+ // Count the number of needed sections.
+ uint32_t Count = Sec->numRelocations();
if (!Count)
continue;
StringRef Name;
- if (OSec->Type == WASM_SEC_DATA)
+ if (Sec->Type == WASM_SEC_DATA)
Name = "reloc.DATA";
- else if (OSec->Type == WASM_SEC_CODE)
+ else if (Sec->Type == WASM_SEC_CODE)
Name = "reloc.CODE";
- else if (OSec->Type == WASM_SEC_CUSTOM)
- Name = Saver.save("reloc." + OSec->Name);
+ else if (Sec->Type == WASM_SEC_CUSTOM)
+ Name = Saver.save("reloc." + Sec->Name);
else
llvm_unreachable(
"relocations only supported for code, data, or custom sections");
- OutputSections.push_back(make<RelocSection>(Name, OSec, I));
- }
-}
-
-static uint32_t getWasmFlags(const Symbol *Sym) {
- uint32_t Flags = 0;
- if (Sym->isLocal())
- Flags |= WASM_SYMBOL_BINDING_LOCAL;
- if (Sym->isWeak())
- Flags |= WASM_SYMBOL_BINDING_WEAK;
- if (Sym->isHidden())
- Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
- if (Sym->isUndefined())
- Flags |= WASM_SYMBOL_UNDEFINED;
- if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
- if (F->getName() != F->ImportName)
- Flags |= WASM_SYMBOL_EXPLICIT_NAME;
- } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
- if (G->getName() != G->ImportName)
- Flags |= WASM_SYMBOL_EXPLICIT_NAME;
- }
- return Flags;
-}
-
-// Some synthetic sections (e.g. "name" and "linking") have subsections.
-// Just like the synthetic sections themselves these need to be created before
-// they can be written out (since they are preceded by their length). This
-// class is used to create subsections and then write them into the stream
-// of the parent section.
-class SubSection {
-public:
- explicit SubSection(uint32_t Type) : Type(Type) {}
-
- void writeTo(raw_ostream &To) {
- OS.flush();
- writeUleb128(To, Type, "subsection type");
- writeUleb128(To, Body.size(), "subsection size");
- To.write(Body.data(), Body.size());
- }
-
-private:
- uint32_t Type;
- std::string Body;
-
-public:
- raw_string_ostream OS{Body};
-};
-
-// Create the custom "dylink" section containing information for the dynamic
-// linker.
-// See
-// https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
-void Writer::createDylinkSection() {
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "dylink");
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, MemSize, "MemSize");
- writeUleb128(OS, MemAlign, "MemAlign");
- writeUleb128(OS, IndirectFunctions.size(), "TableSize");
- writeUleb128(OS, 0, "TableAlign");
- writeUleb128(OS, Symtab->SharedFiles.size(), "Needed");
- for (auto *SO : Symtab->SharedFiles)
- writeStr(OS, llvm::sys::path::filename(SO->getName()), "so name");
-}
-
-// Create the custom "linking" section containing linker metadata.
-// This is only created when relocatable output is requested.
-void Writer::createLinkingSection() {
- SyntheticSection *Section =
- createSyntheticSection(WASM_SEC_CUSTOM, "linking");
- raw_ostream &OS = Section->getStream();
-
- writeUleb128(OS, WasmMetadataVersion, "Version");
-
- if (!SymtabEntries.empty()) {
- SubSection Sub(WASM_SYMBOL_TABLE);
- writeUleb128(Sub.OS, SymtabEntries.size(), "num symbols");
-
- for (const Symbol *Sym : SymtabEntries) {
- assert(Sym->isDefined() || Sym->isUndefined());
- WasmSymbolType Kind = Sym->getWasmType();
- uint32_t Flags = getWasmFlags(Sym);
-
- writeU8(Sub.OS, Kind, "sym kind");
- writeUleb128(Sub.OS, Flags, "sym flags");
-
- if (auto *F = dyn_cast<FunctionSymbol>(Sym)) {
- writeUleb128(Sub.OS, F->getFunctionIndex(), "index");
- if (Sym->isDefined() ||
- (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
- writeStr(Sub.OS, Sym->getName(), "sym name");
- } else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) {
- writeUleb128(Sub.OS, G->getGlobalIndex(), "index");
- if (Sym->isDefined() ||
- (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
- writeStr(Sub.OS, Sym->getName(), "sym name");
- } else if (auto *E = dyn_cast<EventSymbol>(Sym)) {
- writeUleb128(Sub.OS, E->getEventIndex(), "index");
- if (Sym->isDefined() ||
- (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
- writeStr(Sub.OS, Sym->getName(), "sym name");
- } else if (isa<DataSymbol>(Sym)) {
- writeStr(Sub.OS, Sym->getName(), "sym name");
- if (auto *DataSym = dyn_cast<DefinedData>(Sym)) {
- writeUleb128(Sub.OS, DataSym->getOutputSegmentIndex(), "index");
- writeUleb128(Sub.OS, DataSym->getOutputSegmentOffset(),
- "data offset");
- writeUleb128(Sub.OS, DataSym->getSize(), "data size");
- }
- } else {
- auto *S = cast<SectionSymbol>(Sym);
- writeUleb128(Sub.OS, S->getOutputSectionIndex(), "sym section index");
- }
- }
-
- Sub.writeTo(OS);
+ addSection(make<RelocSection>(Name, Sec));
}
-
- if (Segments.size()) {
- SubSection Sub(WASM_SEGMENT_INFO);
- writeUleb128(Sub.OS, Segments.size(), "num data segments");
- for (const OutputSegment *S : Segments) {
- writeStr(Sub.OS, S->Name, "segment name");
- writeUleb128(Sub.OS, S->Alignment, "alignment");
- writeUleb128(Sub.OS, 0, "flags");
- }
- Sub.writeTo(OS);
- }
-
- if (!InitFunctions.empty()) {
- SubSection Sub(WASM_INIT_FUNCS);
- writeUleb128(Sub.OS, InitFunctions.size(), "num init functions");
- for (const WasmInitEntry &F : InitFunctions) {
- writeUleb128(Sub.OS, F.Priority, "priority");
- writeUleb128(Sub.OS, F.Sym->getOutputSymbolIndex(), "function index");
- }
- Sub.writeTo(OS);
- }
-
- struct ComdatEntry {
- unsigned Kind;
- uint32_t Index;
- };
- std::map<StringRef, std::vector<ComdatEntry>> Comdats;
-
- for (const InputFunction *F : InputFunctions) {
- StringRef Comdat = F->getComdatName();
- if (!Comdat.empty())
- Comdats[Comdat].emplace_back(
- ComdatEntry{WASM_COMDAT_FUNCTION, F->getFunctionIndex()});
- }
- for (uint32_t I = 0; I < Segments.size(); ++I) {
- const auto &InputSegments = Segments[I]->InputSegments;
- if (InputSegments.empty())
- continue;
- StringRef Comdat = InputSegments[0]->getComdatName();
-#ifndef NDEBUG
- for (const InputSegment *IS : InputSegments)
- assert(IS->getComdatName() == Comdat);
-#endif
- if (!Comdat.empty())
- Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I});
- }
-
- if (!Comdats.empty()) {
- SubSection Sub(WASM_COMDAT_INFO);
- writeUleb128(Sub.OS, Comdats.size(), "num comdats");
- for (const auto &C : Comdats) {
- writeStr(Sub.OS, C.first, "comdat name");
- writeUleb128(Sub.OS, 0, "comdat flags"); // flags for future use
- writeUleb128(Sub.OS, C.second.size(), "num entries");
- for (const ComdatEntry &Entry : C.second) {
- writeU8(Sub.OS, Entry.Kind, "entry kind");
- writeUleb128(Sub.OS, Entry.Index, "entry index");
- }
- }
- Sub.writeTo(OS);
- }
-}
-
-// Create the custom "name" section containing debug symbol names.
-void Writer::createNameSection() {
- unsigned NumNames = NumImportedFunctions;
- for (const InputFunction *F : InputFunctions)
- if (!F->getName().empty() || !F->getDebugName().empty())
- ++NumNames;
-
- if (NumNames == 0)
- return;
-
- SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name");
-
- SubSection Sub(WASM_NAMES_FUNCTION);
- writeUleb128(Sub.OS, NumNames, "name count");
-
- // Names must appear in function index order. As it happens ImportedSymbols
- // and InputFunctions are numbered in order with imported functions coming
- // first.
- for (const Symbol *S : ImportedSymbols) {
- if (auto *F = dyn_cast<FunctionSymbol>(S)) {
- writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
- writeStr(Sub.OS, toString(*S), "symbol name");
- }
- }
- for (const InputFunction *F : InputFunctions) {
- if (!F->getName().empty()) {
- writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
- if (!F->getDebugName().empty()) {
- writeStr(Sub.OS, F->getDebugName(), "symbol name");
- } else {
- writeStr(Sub.OS, maybeDemangleSymbol(F->getName()), "symbol name");
- }
- }
- }
-
- Sub.writeTo(Section->getStream());
}
-void Writer::createProducersSection() {
- SmallVector<std::pair<std::string, std::string>, 8> Languages;
- SmallVector<std::pair<std::string, std::string>, 8> Tools;
- SmallVector<std::pair<std::string, std::string>, 8> SDKs;
+void Writer::populateProducers() {
for (ObjFile *File : Symtab->ObjectFiles) {
const WasmProducerInfo &Info = File->getWasmObj()->getProducerInfo();
- for (auto &Producers : {std::make_pair(&Info.Languages, &Languages),
- std::make_pair(&Info.Tools, &Tools),
- std::make_pair(&Info.SDKs, &SDKs)})
- for (auto &Producer : *Producers.first)
- if (Producers.second->end() ==
- llvm::find_if(*Producers.second,
- [&](std::pair<std::string, std::string> Seen) {
- return Seen.first == Producer.first;
- }))
- Producers.second->push_back(Producer);
- }
- int FieldCount =
- int(!Languages.empty()) + int(!Tools.empty()) + int(!SDKs.empty());
- if (FieldCount == 0)
- return;
- SyntheticSection *Section =
- createSyntheticSection(WASM_SEC_CUSTOM, "producers");
- auto &OS = Section->getStream();
- writeUleb128(OS, FieldCount, "field count");
- for (auto &Field :
- {std::make_pair("language", Languages),
- std::make_pair("processed-by", Tools), std::make_pair("sdk", SDKs)}) {
- if (Field.second.empty())
- continue;
- writeStr(OS, Field.first, "field name");
- writeUleb128(OS, Field.second.size(), "number of entries");
- for (auto &Entry : Field.second) {
- writeStr(OS, Entry.first, "producer name");
- writeStr(OS, Entry.second, "producer version");
- }
- }
-}
-
-void Writer::createTargetFeaturesSection() {
- if (TargetFeatures.empty())
- return;
-
- SmallVector<std::string, 8> Emitted(TargetFeatures.begin(),
- TargetFeatures.end());
- llvm::sort(Emitted);
- SyntheticSection *Section =
- createSyntheticSection(WASM_SEC_CUSTOM, "target_features");
- auto &OS = Section->getStream();
- writeUleb128(OS, Emitted.size(), "feature count");
- for (auto &Feature : Emitted) {
- writeU8(OS, WASM_FEATURE_PREFIX_USED, "feature used prefix");
- writeStr(OS, Feature, "feature name");
+ Out.ProducersSec->addInfo(Info);
}
}
@@ -749,7 +179,10 @@ void Writer::writeHeader() {
void Writer::writeSections() {
uint8_t *Buf = Buffer->getBufferStart();
- parallelForEach(OutputSections, [Buf](OutputSection *S) { S->writeTo(Buf); });
+ parallelForEach(OutputSections, [Buf](OutputSection *S) {
+ assert(S->isNeeded());
+ S->writeTo(Buf);
+ });
}
// Fix the memory layout of the output binary. This assigns memory offsets
@@ -766,8 +199,6 @@ void Writer::writeSections() {
// rather than overwriting global data, but also increases code size since all
// static data loads and stores requires larger offsets.
void Writer::layoutMemory() {
- createOutputSegments();
-
uint32_t MemoryPtr = 0;
auto PlaceStack = [&]() {
@@ -798,9 +229,9 @@ void Writer::layoutMemory() {
if (WasmSym::DsoHandle)
WasmSym::DsoHandle->setVirtualAddress(DataStart);
- MemAlign = 0;
+ Out.DylinkSec->MemAlign = 0;
for (OutputSegment *Seg : Segments) {
- MemAlign = std::max(MemAlign, Seg->Alignment);
+ Out.DylinkSec->MemAlign = std::max(Out.DylinkSec->MemAlign, Seg->Alignment);
MemoryPtr = alignTo(MemoryPtr, 1ULL << Seg->Alignment);
Seg->StartVA = MemoryPtr;
log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Seg->Name,
@@ -815,7 +246,7 @@ void Writer::layoutMemory() {
log("mem: static data = " + Twine(MemoryPtr - DataStart));
if (Config->Shared) {
- MemSize = MemoryPtr;
+ Out.DylinkSec->MemSize = MemoryPtr;
return;
}
@@ -838,9 +269,10 @@ void Writer::layoutMemory() {
else
MemoryPtr = Config->InitialMemory;
}
- MemSize = MemoryPtr;
- NumMemoryPages = alignTo(MemoryPtr, WasmPageSize) / WasmPageSize;
- log("mem: total pages = " + Twine(NumMemoryPages));
+ Out.DylinkSec->MemSize = MemoryPtr;
+ Out.MemorySec->NumMemoryPages =
+ alignTo(MemoryPtr, WasmPageSize) / WasmPageSize;
+ log("mem: total pages = " + Twine(Out.MemorySec->NumMemoryPages));
// Check max if explicitly supplied or required by shared memory
if (Config->MaxMemory != 0 || Config->SharedMemory) {
@@ -848,51 +280,48 @@ void Writer::layoutMemory() {
error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned");
if (MemoryPtr > Config->MaxMemory)
error("maximum memory too small, " + Twine(MemoryPtr) + " bytes needed");
- MaxMemoryPages = Config->MaxMemory / WasmPageSize;
- log("mem: max pages = " + Twine(MaxMemoryPages));
+ Out.MemorySec->MaxMemoryPages = Config->MaxMemory / WasmPageSize;
+ log("mem: max pages = " + Twine(Out.MemorySec->MaxMemoryPages));
}
}
-SyntheticSection *Writer::createSyntheticSection(uint32_t Type,
- StringRef Name) {
- auto Sec = make<SyntheticSection>(Type, Name);
- log("createSection: " + toString(*Sec));
+void Writer::addSection(OutputSection *Sec) {
+ if (!Sec->isNeeded())
+ return;
+ log("addSection: " + toString(*Sec));
+ Sec->SectionIndex = OutputSections.size();
OutputSections.push_back(Sec);
- return Sec;
}
-void Writer::createSections() {
- // Known sections
- if (Config->Pic)
- createDylinkSection();
- createTypeSection();
- createImportSection();
- createFunctionSection();
- createTableSection();
- createMemorySection();
- createGlobalSection();
- createEventSection();
- createExportSection();
- createElemSection();
- createDataCountSection();
- createCodeSection();
- createDataSection();
+void Writer::addSections() {
+ addSection(Out.DylinkSec);
+ addSection(Out.TypeSec);
+ addSection(Out.ImportSec);
+ addSection(Out.FunctionSec);
+ addSection(Out.TableSec);
+ addSection(Out.MemorySec);
+ addSection(Out.GlobalSec);
+ addSection(Out.EventSec);
+ addSection(Out.ExportSec);
+ addSection(Out.ElemSec);
+ addSection(Out.DataCountSec);
+
+ addSection(make<CodeSection>(Out.FunctionSec->InputFunctions));
+ addSection(make<DataSection>(Segments));
+
createCustomSections();
- // Custom sections
+ addSection(Out.LinkingSec);
if (Config->Relocatable) {
- createLinkingSection();
createRelocSections();
}
- if (!Config->StripDebug && !Config->StripAll)
- createNameSection();
-
- if (!Config->StripAll) {
- createProducersSection();
- createTargetFeaturesSection();
- }
+ addSection(Out.NameSec);
+ addSection(Out.ProducersSec);
+ addSection(Out.TargetFeaturesSec);
+}
+void Writer::finalizeSections() {
for (OutputSection *S : OutputSections) {
S->setOffset(FileSize);
S->finalizeContents();
@@ -900,7 +329,7 @@ void Writer::createSections() {
}
}
-void Writer::calculateTargetFeatures() {
+void Writer::populateTargetFeatures() {
SmallSet<std::string, 8> Used;
SmallSet<std::string, 8> Required;
SmallSet<std::string, 8> Disallowed;
@@ -910,7 +339,7 @@ void Writer::calculateTargetFeatures() {
if (!InferFeatures) {
for (auto &Feature : Config->Features.getValue())
- TargetFeatures.insert(Feature);
+ Out.TargetFeaturesSec->Features.insert(Feature);
// No need to read or check features
if (!Config->CheckFeatures)
return;
@@ -938,9 +367,9 @@ void Writer::calculateTargetFeatures() {
}
if (InferFeatures)
- TargetFeatures.insert(Used.begin(), Used.end());
+ Out.TargetFeaturesSec->Features.insert(Used.begin(), Used.end());
- if (TargetFeatures.count("atomics") && !Config->SharedMemory)
+ if (Out.TargetFeaturesSec->Features.count("atomics") && !Config->SharedMemory)
error("'atomics' feature is used, so --shared-memory must be used");
if (!Config->CheckFeatures)
@@ -953,7 +382,7 @@ void Writer::calculateTargetFeatures() {
// Validate that used features are allowed in output
if (!InferFeatures) {
for (auto &Feature : Used) {
- if (!TargetFeatures.count(Feature))
+ if (!Out.TargetFeaturesSec->Features.count(Feature))
error(Twine("Target feature '") + Feature + "' is not allowed.");
}
}
@@ -993,13 +422,7 @@ void Writer::calculateImports() {
continue;
LLVM_DEBUG(dbgs() << "import: " << Sym->getName() << "\n");
- ImportedSymbols.emplace_back(Sym);
- if (auto *F = dyn_cast<FunctionSymbol>(Sym))
- F->setFunctionIndex(NumImportedFunctions++);
- else if (auto *G = dyn_cast<GlobalSymbol>(Sym))
- G->setGlobalIndex(NumImportedGlobals++);
- else
- cast<EventSymbol>(Sym)->setEventIndex(NumImportedEvents++);
+ Out.ImportSec->addImport(Sym);
}
}
@@ -1008,12 +431,15 @@ void Writer::calculateExports() {
return;
if (!Config->Relocatable && !Config->ImportMemory)
- Exports.push_back(WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0});
+ Out.ExportSec->Exports.push_back(
+ WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0});
if (!Config->Relocatable && Config->ExportTable)
- Exports.push_back(WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0});
+ Out.ExportSec->Exports.push_back(
+ WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0});
- unsigned FakeGlobalIndex = NumImportedGlobals + InputGlobals.size();
+ unsigned FakeGlobalIndex =
+ Out.ImportSec->NumImportedGlobals + Out.GlobalSec->InputGlobals.size();
for (Symbol *Sym : Symtab->getSymbols()) {
if (!Sym->isExported())
@@ -1039,78 +465,31 @@ void Writer::calculateExports() {
Export = {Name, WASM_EXTERNAL_EVENT, E->getEventIndex()};
} else {
auto *D = cast<DefinedData>(Sym);
- DefinedFakeGlobals.emplace_back(D);
+ Out.GlobalSec->DefinedFakeGlobals.emplace_back(D);
Export = {Name, WASM_EXTERNAL_GLOBAL, FakeGlobalIndex++};
}
LLVM_DEBUG(dbgs() << "Export: " << Name << "\n");
- Exports.push_back(Export);
+ Out.ExportSec->Exports.push_back(Export);
}
}
-void Writer::assignSymtab() {
+void Writer::populateSymtab() {
if (!Config->Relocatable)
return;
- StringMap<uint32_t> SectionSymbolIndices;
-
- unsigned SymbolIndex = SymtabEntries.size();
-
- auto AddSymbol = [&](Symbol *Sym) {
- if (auto *S = dyn_cast<SectionSymbol>(Sym)) {
- StringRef Name = S->getName();
- if (CustomSectionMapping.count(Name) == 0)
- return;
-
- auto SSI = SectionSymbolIndices.find(Name);
- if (SSI != SectionSymbolIndices.end()) {
- Sym->setOutputSymbolIndex(SSI->second);
- return;
- }
-
- SectionSymbolIndices[Name] = SymbolIndex;
- CustomSectionSymbols[Name] = cast<SectionSymbol>(Sym);
-
- Sym->markLive();
- }
-
- // (Since this is relocatable output, GC is not performed so symbols must
- // be live.)
- assert(Sym->isLive());
- Sym->setOutputSymbolIndex(SymbolIndex++);
- SymtabEntries.emplace_back(Sym);
- };
-
for (Symbol *Sym : Symtab->getSymbols())
if (Sym->IsUsedInRegularObj)
- AddSymbol(Sym);
+ Out.LinkingSec->addToSymtab(Sym);
for (ObjFile *File : Symtab->ObjectFiles) {
LLVM_DEBUG(dbgs() << "Local symtab entries: " << File->getName() << "\n");
for (Symbol *Sym : File->getSymbols())
- if (Sym->isLocal())
- AddSymbol(Sym);
+ if (Sym->isLocal() && !isa<SectionSymbol>(Sym))
+ Out.LinkingSec->addToSymtab(Sym);
}
}
-uint32_t Writer::lookupType(const WasmSignature &Sig) {
- auto It = TypeIndices.find(Sig);
- if (It == TypeIndices.end()) {
- error("type not found: " + toString(Sig));
- return 0;
- }
- return It->second;
-}
-
-uint32_t Writer::registerType(const WasmSignature &Sig) {
- auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size()));
- if (Pair.second) {
- LLVM_DEBUG(dbgs() << "type " << toString(Sig) << "\n");
- Types.push_back(&Sig);
- }
- return Pair.first->second;
-}
-
void Writer::calculateTypes() {
// The output type section is the union of the following sets:
// 1. Any signature used in the TYPE relocation
@@ -1123,162 +502,62 @@ void Writer::calculateTypes() {
ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
for (uint32_t I = 0; I < Types.size(); I++)
if (File->TypeIsUsed[I])
- File->TypeMap[I] = registerType(Types[I]);
+ File->TypeMap[I] = Out.TypeSec->registerType(Types[I]);
}
- for (const Symbol *Sym : ImportedSymbols) {
+ for (const Symbol *Sym : Out.ImportSec->ImportedSymbols) {
if (auto *F = dyn_cast<FunctionSymbol>(Sym))
- registerType(*F->Signature);
+ Out.TypeSec->registerType(*F->Signature);
else if (auto *E = dyn_cast<EventSymbol>(Sym))
- registerType(*E->Signature);
+ Out.TypeSec->registerType(*E->Signature);
}
- for (const InputFunction *F : InputFunctions)
- registerType(F->Signature);
+ for (const InputFunction *F : Out.FunctionSec->InputFunctions)
+ Out.TypeSec->registerType(F->Signature);
- for (const InputEvent *E : InputEvents)
- registerType(E->Signature);
+ for (const InputEvent *E : Out.EventSec->InputEvents)
+ Out.TypeSec->registerType(E->Signature);
}
-static bool requiresGOTAccess(const Symbol* Sym) {
- return Config->Pic && !Sym->isHidden() && !Sym->isLocal();
-}
-
-void Writer::processRelocations(InputChunk *Chunk) {
- if (!Chunk->Live)
- return;
- ObjFile *File = Chunk->File;
- ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
- for (const WasmRelocation &Reloc : Chunk->getRelocations()) {
- if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) {
- // Mark target type as live
- File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]);
- File->TypeIsUsed[Reloc.Index] = true;
- continue;
- }
-
- // Other relocation types all have a corresponding symbol
- auto *Sym = File->getSymbols()[Reloc.Index];
- switch (Reloc.Type) {
- case R_WASM_TABLE_INDEX_I32:
- case R_WASM_TABLE_INDEX_SLEB:
- case R_WASM_TABLE_INDEX_REL_SLEB: {
- auto *F = cast<FunctionSymbol>(Sym);
- if (F->hasTableIndex() || !F->hasFunctionIndex() || requiresGOTAccess(F))
- break;
- F->setTableIndex(TableBase + IndirectFunctions.size());
- IndirectFunctions.emplace_back(F);
- break;
- }
- case R_WASM_TYPE_INDEX_LEB:
- break;
- case R_WASM_GLOBAL_INDEX_LEB:
- if (!isa<GlobalSymbol>(Sym) && !Sym->isInGOT()) {
- Sym->setGOTIndex(NumImportedGlobals++);
- GOTSymbols.push_back(Sym);
- }
- break;
- case R_WASM_MEMORY_ADDR_SLEB:
- case R_WASM_MEMORY_ADDR_LEB:
- case R_WASM_MEMORY_ADDR_REL_SLEB:
- if (!Config->Relocatable) {
- if (Sym->isUndefined() && !Sym->isWeak()) {
- error(toString(File) + ": cannot resolve relocation of type " +
- relocTypeToString(Reloc.Type) +
- " against undefined (non-weak) data symbol: " + toString(*Sym));
- }
- }
- break;
- }
-
- if (Config->Pic) {
- switch (Reloc.Type) {
- case R_WASM_TABLE_INDEX_SLEB:
- case R_WASM_MEMORY_ADDR_SLEB:
- case R_WASM_MEMORY_ADDR_LEB:
- // Certain relocation types can't be used when building PIC output, since
- // they would require absolute symbol addresses at link time.
- error(toString(File) + ": relocation " +
- relocTypeToString(Reloc.Type) + " cannot be used againt symbol " +
- toString(*Sym) + "; recompile with -fPIC");
- break;
- case R_WASM_TABLE_INDEX_I32:
- case R_WASM_MEMORY_ADDR_I32:
- // These relocation types are only present in the data section and
- // will be converted into code by `generateRelocationCode`. This code
- // requires the symbols to have GOT entires.
- if (requiresGOTAccess(Sym) && !Sym->isInGOT()) {
- Sym->setGOTIndex(NumImportedGlobals++);
- GOTSymbols.push_back(Sym);
- }
- break;
- }
- }
+static void scanRelocations() {
+ for (ObjFile *File : Symtab->ObjectFiles) {
+ LLVM_DEBUG(dbgs() << "scanRelocations: " << File->getName() << "\n");
+ for (InputChunk *Chunk : File->Functions)
+ scanRelocations(Chunk);
+ for (InputChunk *Chunk : File->Segments)
+ scanRelocations(Chunk);
+ for (auto &P : File->CustomSections)
+ scanRelocations(P);
}
}
void Writer::assignIndexes() {
- assert(InputFunctions.empty());
- uint32_t FunctionIndex = NumImportedFunctions;
- auto AddDefinedFunction = [&](InputFunction *Func) {
- if (!Func->Live)
- return;
- InputFunctions.emplace_back(Func);
- Func->setFunctionIndex(FunctionIndex++);
- };
+ assert(Out.FunctionSec->InputFunctions.empty());
for (InputFunction *Func : Symtab->SyntheticFunctions)
- AddDefinedFunction(Func);
+ Out.FunctionSec->addFunction(Func);
for (ObjFile *File : Symtab->ObjectFiles) {
LLVM_DEBUG(dbgs() << "Functions: " << File->getName() << "\n");
for (InputFunction *Func : File->Functions)
- AddDefinedFunction(Func);
- }
-
- for (ObjFile *File : Symtab->ObjectFiles) {
- LLVM_DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n");
- for (InputChunk *Chunk : File->Functions)
- processRelocations(Chunk);
- for (InputChunk *Chunk : File->Segments)
- processRelocations(Chunk);
- for (auto &P : File->CustomSections)
- processRelocations(P);
+ Out.FunctionSec->addFunction(Func);
}
- assert(InputGlobals.empty());
- uint32_t GlobalIndex = NumImportedGlobals;
- auto AddDefinedGlobal = [&](InputGlobal *Global) {
- if (Global->Live) {
- LLVM_DEBUG(dbgs() << "AddDefinedGlobal: " << GlobalIndex << "\n");
- Global->setGlobalIndex(GlobalIndex++);
- InputGlobals.push_back(Global);
- }
- };
+ scanRelocations();
for (InputGlobal *Global : Symtab->SyntheticGlobals)
- AddDefinedGlobal(Global);
+ Out.GlobalSec->addGlobal(Global);
for (ObjFile *File : Symtab->ObjectFiles) {
LLVM_DEBUG(dbgs() << "Globals: " << File->getName() << "\n");
for (InputGlobal *Global : File->Globals)
- AddDefinedGlobal(Global);
+ Out.GlobalSec->addGlobal(Global);
}
- assert(InputEvents.empty());
- uint32_t EventIndex = NumImportedEvents;
- auto AddDefinedEvent = [&](InputEvent *Event) {
- if (Event->Live) {
- LLVM_DEBUG(dbgs() << "AddDefinedEvent: " << EventIndex << "\n");
- Event->setEventIndex(EventIndex++);
- InputEvents.push_back(Event);
- }
- };
-
for (ObjFile *File : Symtab->ObjectFiles) {
LLVM_DEBUG(dbgs() << "Events: " << File->getName() << "\n");
for (InputEvent *Event : File->Events)
- AddDefinedEvent(Event);
+ Out.EventSec->addEvent(Event);
}
}
@@ -1408,6 +687,24 @@ void Writer::calculateInitFunctions() {
});
}
+void Writer::createSyntheticSections() {
+ Out.DylinkSec = make<DylinkSection>();
+ Out.TypeSec = make<TypeSection>();
+ Out.ImportSec = make<ImportSection>();
+ Out.FunctionSec = make<FunctionSection>();
+ Out.TableSec = make<TableSection>();
+ Out.MemorySec = make<MemorySection>();
+ Out.GlobalSec = make<GlobalSection>();
+ Out.EventSec = make<EventSection>();
+ Out.ExportSec = make<ExportSection>();
+ Out.ElemSec = make<ElemSection>(TableBase);
+ Out.DataCountSec = make<DataCountSection>(Segments.size());
+ Out.LinkingSec = make<LinkingSection>(InitFunctions, Segments);
+ Out.NameSec = make<NameSection>();
+ Out.ProducersSec = make<ProducersSection>();
+ Out.TargetFeaturesSec = make<TargetFeaturesSection>();
+}
+
void Writer::run() {
if (Config->Relocatable || Config->Pic)
Config->GlobalBase = 0;
@@ -1417,8 +714,14 @@ void Writer::run() {
if (!Config->Pic)
TableBase = 1;
- log("-- calculateTargetFeatures");
- calculateTargetFeatures();
+ log("-- createOutputSegments");
+ createOutputSegments();
+ log("-- createSyntheticSections");
+ createSyntheticSections();
+ log("-- populateProducers");
+ populateProducers();
+ log("-- populateTargetFeatures");
+ populateTargetFeatures();
log("-- calculateImports");
calculateImports();
log("-- assignIndexes");
@@ -1438,23 +741,25 @@ void Writer::run() {
calculateExports();
log("-- calculateCustomSections");
calculateCustomSections();
- log("-- assignSymtab");
- assignSymtab();
+ log("-- populateSymtab");
+ populateSymtab();
+ log("-- addSections");
+ addSections();
if (errorHandler().Verbose) {
- log("Defined Functions: " + Twine(InputFunctions.size()));
- log("Defined Globals : " + Twine(InputGlobals.size()));
- log("Defined Events : " + Twine(InputEvents.size()));
- log("Function Imports : " + Twine(NumImportedFunctions));
- log("Global Imports : " + Twine(NumImportedGlobals));
- log("Event Imports : " + Twine(NumImportedEvents));
+ log("Defined Functions: " + Twine(Out.FunctionSec->InputFunctions.size()));
+ log("Defined Globals : " + Twine(Out.GlobalSec->InputGlobals.size()));
+ log("Defined Events : " + Twine(Out.EventSec->InputEvents.size()));
+ log("Function Imports : " + Twine(Out.ImportSec->NumImportedFunctions));
+ log("Global Imports : " + Twine(Out.ImportSec->NumImportedGlobals));
+ log("Event Imports : " + Twine(Out.ImportSec->NumImportedEvents));
for (ObjFile *File : Symtab->ObjectFiles)
File->dumpInfo();
}
createHeader();
- log("-- createSections");
- createSections();
+ log("-- finalizeSections");
+ finalizeSections();
log("-- openFile");
openFile();
Modified: lld/trunk/wasm/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.h?rev=361233&r1=361232&r2=361233&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.h (original)
+++ lld/trunk/wasm/Writer.h Tue May 21 02:13:09 2019
@@ -14,8 +14,6 @@ namespace wasm {
void writeResult();
-extern const char *DefaultModule;
-
} // namespace wasm
} // namespace lld
More information about the llvm-commits
mailing list