[lld] r322138 - [WebAssembly] Output functions individually
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 9 15:56:44 PST 2018
Author: sbc
Date: Tue Jan 9 15:56:44 2018
New Revision: 322138
URL: http://llvm.org/viewvc/llvm-project?rev=322138&view=rev
Log:
[WebAssembly] Output functions individually
The code section is now written out one function
at a time rather than all the functions in a given
objects being serialized at once.
This change lays the groundwork for supporting
--gc-sections.
Differential Revision: https://reviews.llvm.org/D41315
Added:
lld/trunk/wasm/InputFunction.h (with props)
Modified:
lld/trunk/wasm/InputFiles.cpp
lld/trunk/wasm/InputFiles.h
lld/trunk/wasm/InputSegment.h
lld/trunk/wasm/OutputSections.cpp
lld/trunk/wasm/OutputSections.h
lld/trunk/wasm/SymbolTable.cpp
lld/trunk/wasm/SymbolTable.h
lld/trunk/wasm/Symbols.cpp
lld/trunk/wasm/Symbols.h
lld/trunk/wasm/Writer.cpp
Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Tue Jan 9 15:56:44 2018
@@ -10,6 +10,7 @@
#include "InputFiles.h"
#include "Config.h"
+#include "InputFunction.h"
#include "InputSegment.h"
#include "SymbolTable.h"
#include "lld/Common/ErrorHandler.h"
@@ -43,34 +44,20 @@ Optional<MemoryBufferRef> lld::wasm::rea
}
void ObjFile::dumpInfo() const {
- log("reloc info for: " + getName() + "\n" +
- " FunctionIndexOffset : " + Twine(FunctionIndexOffset) + "\n" +
- " NumFunctionImports : " + Twine(NumFunctionImports()) + "\n" +
- " NumGlobalImports : " + Twine(NumGlobalImports()) + "\n");
+ log("info for: " + getName() + "\n" +
+ " Total Functions : " + Twine(FunctionSymbols.size()) + "\n" +
+ " Total Globals : " + Twine(GlobalSymbols.size()) + "\n" +
+ " Function Imports : " + Twine(NumFunctionImports) + "\n" +
+ " Global Imports : " + Twine(NumGlobalImports) + "\n" +
+ " Table Entries : " + Twine(TableSymbols.size()) + "\n");
}
-bool ObjFile::isImportedFunction(uint32_t Index) const {
- return Index < NumFunctionImports();
-}
-
-Symbol *ObjFile::getFunctionSymbol(uint32_t Index) const {
- return FunctionSymbols[Index];
-}
-
-Symbol *ObjFile::getTableSymbol(uint32_t Index) const {
- return TableSymbols[Index];
-}
-
-Symbol *ObjFile::getGlobalSymbol(uint32_t Index) const {
- return GlobalSymbols[Index];
-}
-
-uint32_t ObjFile::getRelocatedAddress(uint32_t Index) const {
- return getGlobalSymbol(Index)->getVirtualAddress();
+uint32_t ObjFile::getRelocatedAddress(uint32_t GlobalIndex) const {
+ return GlobalSymbols[GlobalIndex]->getVirtualAddress();
}
uint32_t ObjFile::relocateFunctionIndex(uint32_t Original) const {
- Symbol *Sym = getFunctionSymbol(Original);
+ Symbol *Sym = FunctionSymbols[Original];
uint32_t Index = Sym->getOutputIndex();
DEBUG(dbgs() << "relocateFunctionIndex: " << toString(*Sym) << ": "
<< Original << " -> " << Index << "\n");
@@ -82,7 +69,7 @@ uint32_t ObjFile::relocateTypeIndex(uint
}
uint32_t ObjFile::relocateTableIndex(uint32_t Original) const {
- Symbol *Sym = getTableSymbol(Original);
+ Symbol *Sym = TableSymbols[Original];
uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0;
DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original
<< " -> " << Index << "\n");
@@ -90,7 +77,7 @@ uint32_t ObjFile::relocateTableIndex(uin
}
uint32_t ObjFile::relocateGlobalIndex(uint32_t Original) const {
- Symbol *Sym = getGlobalSymbol(Original);
+ Symbol *Sym = GlobalSymbols[Original];
uint32_t Index = Sym->hasOutputIndex() ? Sym->getOutputIndex() : 0;
DEBUG(dbgs() << "relocateGlobalIndex: " << toString(*Sym) << ": " << Original
<< " -> " << Index << "\n");
@@ -125,7 +112,7 @@ void ObjFile::parse() {
}
// Return the InputSegment in which a given symbol is defined.
-InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) {
+InputSegment *ObjFile::getSegment(const WasmSymbol &WasmSym) const {
uint32_t Address = WasmObj->getWasmSymbolValue(WasmSym);
for (InputSegment *Segment : Segments) {
if (Address >= Segment->startVA() && Address < Segment->endVA()) {
@@ -141,37 +128,61 @@ InputSegment *ObjFile::getSegment(const
static void copyRelocationsRange(std::vector<WasmRelocation> &To,
ArrayRef<WasmRelocation> From, size_t Start,
- size_t End) {
+ size_t Size) {
for (const WasmRelocation &R : From)
- if (R.Offset >= Start && R.Offset < End)
+ if (R.Offset >= Start && R.Offset < Start + Size)
To.push_back(R);
}
+// Get the signature for a given function symbol, either by looking
+// it up in function sections (for defined functions), of the imports section
+// (for imported functions).
+const WasmSignature *ObjFile::getFunctionSig(const WasmSymbol &Sym) const {
+ DEBUG(dbgs() << "getFunctionSig: " << Sym.Name << "\n");
+ return &WasmObj->types()[Sym.FunctionType];
+}
+
+InputFunction *ObjFile::getFunction(const WasmSymbol &Sym) const {
+ uint32_t FunctionIndex = Sym.ElementIndex - NumFunctionImports;
+ return Functions[FunctionIndex];
+}
+
void ObjFile::initializeSymbols() {
Symbols.reserve(WasmObj->getNumberOfSymbols());
for (const WasmImport &Import : WasmObj->imports()) {
switch (Import.Kind) {
case WASM_EXTERNAL_FUNCTION:
- ++FunctionImports;
+ ++NumFunctionImports;
break;
case WASM_EXTERNAL_GLOBAL:
- ++GlobalImports;
+ ++NumGlobalImports;
break;
}
}
- FunctionSymbols.resize(FunctionImports + WasmObj->functions().size());
- GlobalSymbols.resize(GlobalImports + WasmObj->globals().size());
+ FunctionSymbols.resize(NumFunctionImports + WasmObj->functions().size());
+ GlobalSymbols.resize(NumGlobalImports + WasmObj->globals().size());
for (const WasmSegment &S : WasmObj->dataSegments()) {
- InputSegment *Seg = make<InputSegment>(&S, this);
+ InputSegment *Seg = make<InputSegment>(S, *this);
copyRelocationsRange(Seg->Relocations, DataSection->Relocations,
- Seg->getInputSectionOffset(),
- Seg->getInputSectionOffset() + Seg->getSize());
+ Seg->getInputSectionOffset(), Seg->getSize());
Segments.emplace_back(Seg);
}
+ ArrayRef<WasmFunction> Funcs = WasmObj->functions();
+ ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();
+ ArrayRef<WasmSignature> Types = WasmObj->types();
+ for (size_t I = 0; I < Funcs.size(); ++I) {
+ const WasmFunction &Func = Funcs[I];
+ const WasmSignature &Sig = Types[FuncTypes[I]];
+ InputFunction *Function = make<InputFunction>(Sig, Func, *this);
+ copyRelocationsRange(Function->Relocations, CodeSection->Relocations,
+ Func.CodeSectionOffset, Func.Size);
+ Functions.emplace_back(Function);
+ }
+
// Populate `FunctionSymbols` and `GlobalSymbols` based on the WasmSymbols
// in the object
for (const SymbolRef &Sym : WasmObj->symbols()) {
@@ -179,14 +190,16 @@ void ObjFile::initializeSymbols() {
Symbol *S;
switch (WasmSym.Type) {
case WasmSymbol::SymbolType::FUNCTION_IMPORT:
+ S = createUndefined(WasmSym, getFunctionSig(WasmSym));
+ break;
case WasmSymbol::SymbolType::GLOBAL_IMPORT:
S = createUndefined(WasmSym);
break;
case WasmSymbol::SymbolType::GLOBAL_EXPORT:
- S = createDefined(WasmSym, getSegment(WasmSym));
+ S = createDefined(WasmSym, getSegment(WasmSym), nullptr);
break;
case WasmSymbol::SymbolType::FUNCTION_EXPORT:
- S = createDefined(WasmSym);
+ S = createDefined(WasmSym, nullptr, getFunction(WasmSym));
break;
case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
// These are for debugging only, no need to create linker symbols for them
@@ -228,7 +241,7 @@ void ObjFile::initializeSymbols() {
fatal(getName() + ": unsupported element segment offset");
TableSymbols.reserve(Segment.Functions.size());
for (uint64_t FunctionIndex : Segment.Functions)
- TableSymbols.push_back(getFunctionSymbol(FunctionIndex));
+ TableSymbols.push_back(FunctionSymbols[FunctionIndex]);
}
DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n");
@@ -236,12 +249,14 @@ void ObjFile::initializeSymbols() {
DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n");
}
-Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
- return Symtab->addUndefined(this, &Sym);
+Symbol *ObjFile::createUndefined(const WasmSymbol &Sym,
+ const WasmSignature *Signature) {
+ return Symtab->addUndefined(this, &Sym, Signature);
}
Symbol *ObjFile::createDefined(const WasmSymbol &Sym,
- const InputSegment *Segment) {
+ const InputSegment *Segment,
+ InputFunction *Function) {
Symbol *S;
if (Sym.isLocal()) {
S = make<Symbol>(Sym.Name, true);
@@ -252,10 +267,10 @@ Symbol *ObjFile::createDefined(const Was
Kind = Symbol::Kind::DefinedGlobalKind;
else
llvm_unreachable("invalid local symbol type");
- S->update(Kind, this, &Sym, Segment);
+ S->update(Kind, this, &Sym, Segment, Function);
return S;
}
- return Symtab->addDefined(this, &Sym, Segment);
+ return Symtab->addDefined(this, &Sym, Segment, Function);
}
void ArchiveFile::parse() {
Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Tue Jan 9 15:56:44 2018
@@ -26,11 +26,13 @@ using llvm::object::WasmObjectFile;
using llvm::object::WasmSection;
using llvm::object::WasmSymbol;
using llvm::wasm::WasmImport;
+using llvm::wasm::WasmSignature;
namespace lld {
namespace wasm {
class Symbol;
+class InputFunction;
class InputSegment;
class InputFile {
@@ -95,34 +97,27 @@ public:
uint32_t relocateTableIndex(uint32_t Original) const;
uint32_t getRelocatedAddress(uint32_t Index) const;
- // Returns true if the given function index is an imported function,
- // as opposed to the locally defined function.
- bool isImportedFunction(uint32_t Index) const;
+ size_t getNumGlobalImports() const { return NumGlobalImports; }
- size_t NumFunctionImports() const { return FunctionImports; }
- size_t NumGlobalImports() const { return GlobalImports; }
-
- int32_t FunctionIndexOffset = 0;
const WasmSection *CodeSection = nullptr;
- std::vector<OutputRelocation> CodeRelocations;
- int32_t CodeOffset = 0;
- const WasmSection *DataSection = nullptr;
std::vector<uint32_t> TypeMap;
std::vector<InputSegment *> Segments;
+ std::vector<InputFunction *> Functions;
ArrayRef<Symbol *> getSymbols() { return Symbols; }
ArrayRef<Symbol *> getTableSymbols() { return TableSymbols; }
private:
Symbol *createDefined(const WasmSymbol &Sym,
- const InputSegment *Segment = nullptr);
- Symbol *createUndefined(const WasmSymbol &Sym);
+ const InputSegment *Segment = nullptr,
+ InputFunction *Function = nullptr);
+ Symbol *createUndefined(const WasmSymbol &Sym,
+ const WasmSignature *Signature = nullptr);
void initializeSymbols();
- InputSegment *getSegment(const WasmSymbol &WasmSym);
- Symbol *getFunctionSymbol(uint32_t FunctionIndex) const;
- Symbol *getTableSymbol(uint32_t TableIndex) const;
- Symbol *getGlobalSymbol(uint32_t GlobalIndex) const;
+ InputSegment *getSegment(const WasmSymbol &WasmSym) const;
+ const WasmSignature *getFunctionSig(const WasmSymbol &Sym) const;
+ InputFunction *getFunction(const WasmSymbol &Sym) const;
// List of all symbols referenced or defined by this file.
std::vector<Symbol *> Symbols;
@@ -136,8 +131,9 @@ private:
// List of all indirect symbols indexed by table index space.
std::vector<Symbol *> TableSymbols;
- uint32_t GlobalImports = 0;
- uint32_t FunctionImports = 0;
+ const WasmSection *DataSection = nullptr;
+ uint32_t NumGlobalImports = 0;
+ uint32_t NumFunctionImports = 0;
std::unique_ptr<WasmObjectFile> WasmObj;
};
Added: lld/trunk/wasm/InputFunction.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFunction.h?rev=322138&view=auto
==============================================================================
--- lld/trunk/wasm/InputFunction.h (added)
+++ lld/trunk/wasm/InputFunction.h Tue Jan 9 15:56:44 2018
@@ -0,0 +1,57 @@
+//===- InpuFunction.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Represents a WebAssembly function in an input file which could also be
+// assigned a function index in the output.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_WASM_INPUT_FUNCTION_H
+#define LLD_WASM_INPUT_FUNCTION_H
+
+#include "WriterUtils.h"
+#include "llvm/Object/Wasm.h"
+
+using llvm::wasm::WasmRelocation;
+using llvm::wasm::WasmFunction;
+
+namespace lld {
+namespace wasm {
+
+class ObjFile;
+
+class InputFunction {
+public:
+ InputFunction(const WasmSignature &S, const WasmFunction &Func,
+ const ObjFile &F)
+ : Signature(S), Function(Func), File(F) {}
+
+ uint32_t getOutputIndex() const { return OutputIndex.getValue(); };
+ bool hasOutputIndex() const { return OutputIndex.hasValue(); };
+
+ void setOutputIndex(uint32_t Index) {
+ assert(!hasOutputIndex());
+ OutputIndex = Index;
+ };
+
+ const WasmSignature &Signature;
+ const WasmFunction &Function;
+ int32_t OutputOffset = 0;
+ std::vector<WasmRelocation> Relocations;
+ std::vector<OutputRelocation> OutRelocations;
+ const ObjFile &File;
+
+protected:
+ llvm::Optional<uint32_t> OutputIndex;
+};
+
+} // namespace wasm
+} // namespace lld
+
+#endif // LLD_WASM_INPUT_FUNCTION_H
Propchange: lld/trunk/wasm/InputFunction.h
------------------------------------------------------------------------------
svn:eol-style = LF
Modified: lld/trunk/wasm/InputSegment.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputSegment.h?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/InputSegment.h (original)
+++ lld/trunk/wasm/InputSegment.h Tue Jan 9 15:56:44 2018
@@ -36,7 +36,7 @@ class OutputSegment;
class InputSegment {
public:
- InputSegment(const WasmSegment *Seg, const ObjFile *F)
+ InputSegment(const WasmSegment &Seg, const ObjFile &F)
: Segment(Seg), File(F) {}
// Translate an offset in the input segment to an offset in the output
@@ -47,21 +47,21 @@ public:
uint32_t getOutputSegmentOffset() const { return OutputSegmentOffset; }
- uint32_t getInputSectionOffset() const { return Segment->SectionOffset; }
+ uint32_t getInputSectionOffset() const { return Segment.SectionOffset; }
void setOutputSegment(const OutputSegment *Segment, uint32_t Offset) {
OutputSeg = Segment;
OutputSegmentOffset = Offset;
}
- uint32_t getSize() const { return Segment->Data.Content.size(); }
- uint32_t getAlignment() const { return Segment->Data.Alignment; }
- uint32_t startVA() const { return Segment->Data.Offset.Value.Int32; }
+ uint32_t getSize() const { return Segment.Data.Content.size(); }
+ uint32_t getAlignment() const { return Segment.Data.Alignment; }
+ uint32_t startVA() const { return Segment.Data.Offset.Value.Int32; }
uint32_t endVA() const { return startVA() + getSize(); }
- StringRef getName() const { return Segment->Data.Name; }
+ StringRef getName() const { return Segment.Data.Name; }
- const WasmSegment *Segment;
- const ObjFile *File;
+ const WasmSegment &Segment;
+ const ObjFile &File;
std::vector<WasmRelocation> Relocations;
std::vector<OutputRelocation> OutRelocations;
Modified: lld/trunk/wasm/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.cpp?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.cpp (original)
+++ lld/trunk/wasm/OutputSections.cpp Tue Jan 9 15:56:44 2018
@@ -11,6 +11,7 @@
#include "Config.h"
#include "InputFiles.h"
+#include "InputFunction.h"
#include "OutputSegment.h"
#include "SymbolTable.h"
#include "lld/Common/ErrorHandler.h"
@@ -150,6 +151,7 @@ static void calcRelocations(const ObjFil
for (const WasmRelocation &Reloc : Relocs) {
OutputRelocation NewReloc;
NewReloc.Reloc = Reloc;
+ assert(Reloc.Offset + OutputOffset > 0);
NewReloc.Reloc.Offset += OutputOffset;
DEBUG(dbgs() << "reloc: type=" << Reloc.Type << " index=" << Reloc.Index
<< " offset=" << Reloc.Offset
@@ -191,27 +193,20 @@ void OutputSection::createHeader(size_t
" total=" + Twine(getSize()));
}
-CodeSection::CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs)
- : OutputSection(WASM_SEC_CODE), InputObjects(Objs) {
+CodeSection::CodeSection(ArrayRef<InputFunction *> Functions)
+ : OutputSection(WASM_SEC_CODE), Functions(Functions) {
+ assert(Functions.size() > 0);
+
raw_string_ostream OS(CodeSectionHeader);
- writeUleb128(OS, NumFunctions, "function count");
+ writeUleb128(OS, Functions.size(), "function count");
OS.flush();
BodySize = CodeSectionHeader.size();
- for (ObjFile *File : InputObjects) {
- if (!File->CodeSection)
- continue;
-
- File->CodeOffset = BodySize;
- ArrayRef<uint8_t> Content = File->CodeSection->Content;
- unsigned HeaderSize = 0;
- decodeULEB128(Content.data(), &HeaderSize);
-
- calcRelocations(*File, File->CodeSection->Relocations,
- File->CodeRelocations, BodySize - HeaderSize);
-
- size_t PayloadSize = Content.size() - HeaderSize;
- BodySize += PayloadSize;
+ for (InputFunction *Func : Functions) {
+ Func->OutputOffset = BodySize;
+ calcRelocations(Func->File, Func->Relocations, Func->OutRelocations,
+ Func->OutputOffset - Func->Function.CodeSectionOffset);
+ BodySize += Func->Function.Size;
}
createHeader(BodySize);
@@ -220,6 +215,8 @@ CodeSection::CodeSection(uint32_t NumFun
void CodeSection::writeTo(uint8_t *Buf) {
log("writing " + toString(*this));
log(" size=" + Twine(getSize()));
+ log(" headersize=" + Twine(Header.size()));
+ log(" codeheadersize=" + Twine(CodeSectionHeader.size()));
Buf += Offset;
// Write section header
@@ -233,35 +230,25 @@ void CodeSection::writeTo(uint8_t *Buf)
Buf += CodeSectionHeader.size();
// Write code section bodies
- parallelForEach(InputObjects, [ContentsStart](ObjFile *File) {
- if (!File->CodeSection)
- return;
-
- ArrayRef<uint8_t> Content(File->CodeSection->Content);
-
- // Payload doesn't include the initial header (function count)
- unsigned HeaderSize = 0;
- decodeULEB128(Content.data(), &HeaderSize);
-
- size_t PayloadSize = Content.size() - HeaderSize;
- memcpy(ContentsStart + File->CodeOffset, Content.data() + HeaderSize,
- PayloadSize);
-
- log("applying relocations for: " + File->getName());
- applyRelocations(ContentsStart, File->CodeRelocations);
+ parallelForEach(Functions, [ContentsStart](InputFunction *Func) {
+ ArrayRef<uint8_t> Content(Func->File.CodeSection->Content);
+ memcpy(ContentsStart + Func->OutputOffset,
+ Content.data() + Func->Function.CodeSectionOffset,
+ Func->Function.Size);
+ applyRelocations(ContentsStart, Func->OutRelocations);
});
}
uint32_t CodeSection::numRelocations() const {
uint32_t Count = 0;
- for (ObjFile *File : InputObjects)
- Count += File->CodeRelocations.size();
+ for (const InputFunction *Func : Functions)
+ Count += Func->OutRelocations.size();
return Count;
}
void CodeSection::writeRelocations(raw_ostream &OS) const {
- for (ObjFile *File : InputObjects)
- for (const OutputRelocation &Reloc : File->CodeRelocations)
+ for (const InputFunction *Func : Functions)
+ for (const OutputRelocation &Reloc : Func->OutRelocations)
writeReloc(OS, Reloc);
}
@@ -289,7 +276,7 @@ DataSection::DataSection(ArrayRef<Output
uint32_t OutputOffset = Segment->getSectionOffset() +
Segment->Header.size() +
InputSeg->getOutputSegmentOffset();
- calcRelocations(*InputSeg->File, InputSeg->Relocations,
+ calcRelocations(InputSeg->File, InputSeg->Relocations,
InputSeg->OutRelocations, OutputOffset - InputOffset);
}
BodySize += Segment->Size;
@@ -319,7 +306,7 @@ void DataSection::writeTo(uint8_t *Buf)
// Write segment data payload
for (const InputSegment *Input : Segment->InputSegments) {
- ArrayRef<uint8_t> Content(Input->Segment->Data.Content);
+ ArrayRef<uint8_t> Content(Input->Segment.Data.Content);
memcpy(SegStart + Segment->Header.size() +
Input->getOutputSegmentOffset(),
Content.data(), Content.size());
Modified: lld/trunk/wasm/OutputSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/OutputSections.h?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/OutputSections.h (original)
+++ lld/trunk/wasm/OutputSections.h Tue Jan 9 15:56:44 2018
@@ -28,7 +28,7 @@ std::string toString(const wasm::OutputS
namespace wasm {
class OutputSegment;
-class ObjFile;
+class InputFunction;
class OutputSection {
public:
@@ -104,14 +104,14 @@ public:
class CodeSection : public OutputSection {
public:
- explicit CodeSection(uint32_t NumFunctions, ArrayRef<ObjFile *> Objs);
+ explicit CodeSection(ArrayRef<InputFunction *> Functions);
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;
protected:
- ArrayRef<ObjFile *> InputObjects;
+ ArrayRef<InputFunction *> Functions;
std::string CodeSectionHeader;
size_t BodySize = 0;
};
Modified: lld/trunk/wasm/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.cpp?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.cpp (original)
+++ lld/trunk/wasm/SymbolTable.cpp Tue Jan 9 15:56:44 2018
@@ -10,6 +10,7 @@
#include "SymbolTable.h"
#include "Config.h"
+#include "InputFunction.h"
#include "WriterUtils.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
@@ -76,16 +77,6 @@ void SymbolTable::reportDuplicate(Symbol
toString(NewFile));
}
-// Get the signature for a given function symbol, either by looking
-// it up in function sections (for defined functions), of the imports section
-// (for imported functions).
-static const WasmSignature *getFunctionSig(const ObjFile &Obj,
- const WasmSymbol &Sym) {
- DEBUG(dbgs() << "getFunctionSig: " << Sym.Name << "\n");
- const WasmObjectFile *WasmObj = Obj.getWasmObj();
- return &WasmObj->types()[Sym.FunctionType];
-}
-
// Check the type of new symbol matches that of the symbol is replacing.
// For functions this can also involve verifying that the signatures match.
static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
@@ -140,32 +131,30 @@ Symbol *SymbolTable::addDefinedGlobal(St
}
Symbol *SymbolTable::addDefined(InputFile *F, const WasmSymbol *Sym,
- const InputSegment *Segment) {
+ const InputSegment *Segment,
+ InputFunction *Function) {
DEBUG(dbgs() << "addDefined: " << Sym->Name << "\n");
Symbol *S;
bool WasInserted;
Symbol::Kind Kind = Symbol::DefinedFunctionKind;
- const WasmSignature *NewSig = nullptr;
if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_EXPORT)
Kind = Symbol::DefinedGlobalKind;
- else
- NewSig = getFunctionSig(*cast<ObjFile>(F), *Sym);
std::tie(S, WasInserted) = insert(Sym->Name);
if (WasInserted) {
- S->update(Kind, F, Sym, Segment, NewSig);
+ S->update(Kind, F, Sym, Segment, Function);
} else if (S->isLazy()) {
// The existing symbol is lazy. Replace it without checking types since
// lazy symbols don't have any type information.
DEBUG(dbgs() << "replacing existing lazy symbol: " << Sym->Name << "\n");
- S->update(Kind, F, Sym, Segment, NewSig);
+ S->update(Kind, F, Sym, Segment, Function);
} else if (!S->isDefined()) {
// The existing symbol table entry is undefined. The new symbol replaces
// it, after checking the type matches
DEBUG(dbgs() << "resolving existing undefined symbol: " << Sym->Name
<< "\n");
- checkSymbolTypes(*S, *F, *Sym, NewSig);
- S->update(Kind, F, Sym, Segment, NewSig);
+ checkSymbolTypes(*S, *F, *Sym, Function ? &Function->Signature : nullptr);
+ S->update(Kind, F, Sym, Segment, Function);
} else if (Sym->isWeak()) {
// the new symbol is weak we can ignore it
DEBUG(dbgs() << "existing symbol takes precedence\n");
@@ -173,8 +162,8 @@ Symbol *SymbolTable::addDefined(InputFil
// the new symbol is not weak and the existing symbol is, so we replace
// it
DEBUG(dbgs() << "replacing existing weak symbol\n");
- checkSymbolTypes(*S, *F, *Sym, NewSig);
- S->update(Kind, F, Sym, Segment, NewSig);
+ checkSymbolTypes(*S, *F, *Sym, Function ? &Function->Signature : nullptr);
+ S->update(Kind, F, Sym, Segment, Function);
} else {
// neither symbol is week. They conflict.
reportDuplicate(S, F);
@@ -188,33 +177,34 @@ Symbol *SymbolTable::addUndefinedFunctio
bool WasInserted;
std::tie(S, WasInserted) = insert(Name);
if (WasInserted) {
- S->update(Symbol::UndefinedFunctionKind, nullptr, nullptr, nullptr, Type);
+ S->update(Symbol::UndefinedFunctionKind);
+ S->setFunctionType(Type);
} else if (!S->isFunction()) {
error("symbol type mismatch: " + Name);
}
return S;
}
-Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym) {
+Symbol *SymbolTable::addUndefined(InputFile *F, const WasmSymbol *Sym,
+ const WasmSignature *Type) {
DEBUG(dbgs() << "addUndefined: " << Sym->Name << "\n");
Symbol *S;
bool WasInserted;
Symbol::Kind Kind = Symbol::UndefinedFunctionKind;
- const WasmSignature *NewSig = nullptr;
if (Sym->Type == WasmSymbol::SymbolType::GLOBAL_IMPORT)
Kind = Symbol::UndefinedGlobalKind;
- else
- NewSig = getFunctionSig(*cast<ObjFile>(F), *Sym);
std::tie(S, WasInserted) = insert(Sym->Name);
if (WasInserted) {
- S->update(Kind, F, Sym, nullptr, NewSig);
+ S->update(Kind, F, Sym);
+ if (Type)
+ S->setFunctionType(Type);
} else if (S->isLazy()) {
DEBUG(dbgs() << "resolved by existing lazy\n");
auto *AF = cast<ArchiveFile>(S->getFile());
AF->addMember(&S->getArchiveSymbol());
} else if (S->isDefined()) {
DEBUG(dbgs() << "resolved by existing\n");
- checkSymbolTypes(*S, *F, *Sym, NewSig);
+ checkSymbolTypes(*S, *F, *Sym, Type);
}
return S;
}
Modified: lld/trunk/wasm/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/SymbolTable.h?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/SymbolTable.h (original)
+++ lld/trunk/wasm/SymbolTable.h Tue Jan 9 15:56:44 2018
@@ -50,8 +50,10 @@ public:
Symbol *find(StringRef Name);
Symbol *addDefined(InputFile *F, const WasmSymbol *Sym,
- const InputSegment *Segment = nullptr);
- Symbol *addUndefined(InputFile *F, const WasmSymbol *Sym);
+ const InputSegment *Segment = nullptr,
+ InputFunction *Function = nullptr);
+ Symbol *addUndefined(InputFile *F, const WasmSymbol *Sym,
+ const WasmSignature *Signature = nullptr);
Symbol *addUndefinedFunction(StringRef Name, const WasmSignature *Type);
Symbol *addDefinedGlobal(StringRef Name);
void addLazy(ArchiveFile *F, const Archive::Symbol *Sym);
Modified: lld/trunk/wasm/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.cpp?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.cpp (original)
+++ lld/trunk/wasm/Symbols.cpp Tue Jan 9 15:56:44 2018
@@ -11,6 +11,7 @@
#include "Config.h"
#include "InputFiles.h"
+#include "InputFunction.h"
#include "InputSegment.h"
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Strings.h"
@@ -21,21 +22,20 @@ using namespace llvm;
using namespace lld;
using namespace lld::wasm;
-uint32_t Symbol::getGlobalIndex() const {
- assert(!Sym->isFunction());
- return Sym->ElementIndex;
-}
-
-uint32_t Symbol::getFunctionIndex() const {
- assert(Sym->isFunction());
- return Sym->ElementIndex;
-}
-
const WasmSignature &Symbol::getFunctionType() const {
+ if (Function != nullptr)
+ return Function->Signature;
+
assert(FunctionType != nullptr);
return *FunctionType;
}
+void Symbol::setFunctionType(const WasmSignature *Type) {
+ assert(FunctionType == nullptr);
+ assert(Function == nullptr);
+ FunctionType = Type;
+}
+
uint32_t Symbol::getVirtualAddress() const {
assert(isGlobal());
DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
@@ -44,15 +44,28 @@ uint32_t Symbol::getVirtualAddress() con
if (VirtualAddress.hasValue())
return VirtualAddress.getValue();
- assert(Sym != nullptr);
ObjFile *Obj = cast<ObjFile>(File);
+ assert(Sym != nullptr);
const WasmGlobal &Global =
- Obj->getWasmObj()->globals()[getGlobalIndex() - Obj->NumGlobalImports()];
+ Obj->getWasmObj()
+ ->globals()[Sym->ElementIndex - Obj->getNumGlobalImports()];
assert(Global.Type == llvm::wasm::WASM_TYPE_I32);
assert(Segment);
return Segment->translateVA(Global.InitExpr.Value.Int32);
}
+bool Symbol::hasOutputIndex() const {
+ if (Function)
+ return Function->hasOutputIndex();
+ return OutputIndex.hasValue();
+}
+
+uint32_t Symbol::getOutputIndex() const {
+ if (Function)
+ return Function->getOutputIndex();
+ return OutputIndex.getValue();
+}
+
void Symbol::setVirtualAddress(uint32_t Value) {
DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");
assert(!VirtualAddress.hasValue());
@@ -61,6 +74,7 @@ void Symbol::setVirtualAddress(uint32_t
void Symbol::setOutputIndex(uint32_t Index) {
DEBUG(dbgs() << "setOutputIndex " << Name << " -> " << Index << "\n");
+ assert(!Function);
assert(!OutputIndex.hasValue());
OutputIndex = Index;
}
@@ -72,12 +86,12 @@ void Symbol::setTableIndex(uint32_t Inde
}
void Symbol::update(Kind K, InputFile *F, const WasmSymbol *WasmSym,
- const InputSegment *Seg, const WasmSignature *Sig) {
+ const InputSegment *Seg, const InputFunction *Func) {
SymbolKind = K;
File = F;
Sym = WasmSym;
Segment = Seg;
- FunctionType = Sig;
+ Function = Func;
}
bool Symbol::isWeak() const { return Sym && Sym->isWeak(); }
Modified: lld/trunk/wasm/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Symbols.h?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/Symbols.h (original)
+++ lld/trunk/wasm/Symbols.h Tue Jan 9 15:56:44 2018
@@ -25,6 +25,7 @@ namespace wasm {
class InputFile;
class InputSegment;
+class InputFunction;
class Symbol {
public:
@@ -66,16 +67,14 @@ public:
// Returns the file from which this symbol was created.
InputFile *getFile() const { return File; }
- uint32_t getGlobalIndex() const;
- uint32_t getFunctionIndex() const;
-
bool hasFunctionType() const { return FunctionType != nullptr; }
const WasmSignature &getFunctionType() const;
+ void setFunctionType(const WasmSignature *Type);
- uint32_t getOutputIndex() const { return OutputIndex.getValue(); }
+ uint32_t getOutputIndex() const;
// Returns true if an output index has been set for this symbol
- bool hasOutputIndex() const { return OutputIndex.hasValue(); }
+ bool hasOutputIndex() const;
// Set the output index of the symbol (in the function or global index
// space of the output object.
@@ -97,7 +96,7 @@ public:
void update(Kind K, InputFile *F = nullptr, const WasmSymbol *Sym = nullptr,
const InputSegment *Segment = nullptr,
- const WasmSignature *Sig = nullptr);
+ const InputFunction *Function = nullptr);
void setArchiveSymbol(const Archive::Symbol &Sym) { ArchiveSymbol = Sym; }
const Archive::Symbol &getArchiveSymbol() { return ArchiveSymbol; }
@@ -116,10 +115,11 @@ protected:
InputFile *File = nullptr;
const WasmSymbol *Sym = nullptr;
const InputSegment *Segment = nullptr;
+ const InputFunction *Function = nullptr;
llvm::Optional<uint32_t> OutputIndex;
llvm::Optional<uint32_t> TableIndex;
llvm::Optional<uint32_t> VirtualAddress;
- const WasmSignature *FunctionType;
+ const WasmSignature *FunctionType = nullptr;
};
} // namespace wasm
Modified: lld/trunk/wasm/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/Writer.cpp?rev=322138&r1=322137&r2=322138&view=diff
==============================================================================
--- lld/trunk/wasm/Writer.cpp (original)
+++ lld/trunk/wasm/Writer.cpp Tue Jan 9 15:56:44 2018
@@ -10,6 +10,7 @@
#include "Writer.h"
#include "Config.h"
+#include "InputFunction.h"
#include "OutputSections.h"
#include "OutputSegment.h"
#include "SymbolTable.h"
@@ -68,7 +69,7 @@ private:
void openFile();
uint32_t getTypeIndex(const WasmSignature &Sig);
- void assignSymbolIndexes();
+ void assignIndexes();
void calculateImports();
void calculateOffsets();
void calculateTypes();
@@ -102,15 +103,15 @@ private:
uint64_t FileSize = 0;
uint32_t DataSize = 0;
- uint32_t NumFunctions = 0;
uint32_t NumMemoryPages = 0;
uint32_t InitialTableOffset = 0;
std::vector<const WasmSignature *> Types;
DenseMap<WasmSignature, int32_t, WasmSignatureDenseMapInfo> TypeIndices;
- std::vector<const Symbol *> FunctionImports;
- std::vector<const Symbol *> GlobalImports;
+ std::vector<const Symbol *> ImportedFunctions;
+ std::vector<const Symbol *> ImportedGlobals;
std::vector<const Symbol *> DefinedGlobals;
+ std::vector<InputFunction *> DefinedFunctions;
std::vector<const Symbol *> IndirectFunctions;
// Elements that are used to construct the final output
@@ -136,7 +137,7 @@ static void debugPrint(const char *fmt,
}
void Writer::createImportSection() {
- uint32_t NumImports = FunctionImports.size() + GlobalImports.size();
+ uint32_t NumImports = ImportedFunctions.size() + ImportedGlobals.size();
if (Config->ImportMemory)
++NumImports;
@@ -148,7 +149,7 @@ void Writer::createImportSection() {
writeUleb128(OS, NumImports, "import count");
- for (const Symbol *Sym : FunctionImports) {
+ for (const Symbol *Sym : ImportedFunctions) {
WasmImport Import;
Import.Module = "env";
Import.Field = Sym->getName();
@@ -168,7 +169,7 @@ void Writer::createImportSection() {
writeImport(OS, Import);
}
- for (const Symbol *Sym : GlobalImports) {
+ for (const Symbol *Sym : ImportedGlobals) {
WasmImport Import;
Import.Module = "env";
Import.Field = Sym->getName();
@@ -188,16 +189,15 @@ void Writer::createTypeSection() {
}
void Writer::createFunctionSection() {
- if (!NumFunctions)
+ if (DefinedFunctions.empty())
return;
SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION);
raw_ostream &OS = Section->getStream();
- writeUleb128(OS, NumFunctions, "function count");
- for (ObjFile *File : Symtab->ObjectFiles)
- for (uint32_t Sig : File->getWasmObj()->functionTypes())
- writeUleb128(OS, File->relocateTypeIndex(Sig), "sig index");
+ writeUleb128(OS, DefinedFunctions.size(), "function count");
+ for (const InputFunction *Func : DefinedFunctions)
+ writeUleb128(OS, TypeIndices.lookup(Func->Signature), "sig index");
}
void Writer::createMemorySection() {
@@ -337,12 +337,12 @@ void Writer::createElemSection() {
}
void Writer::createCodeSection() {
- if (!NumFunctions)
+ if (DefinedFunctions.empty())
return;
log("createCodeSection");
- auto Section = make<CodeSection>(NumFunctions, Symtab->ObjectFiles);
+ auto Section = make<CodeSection>(DefinedFunctions);
OutputSections.push_back(Section);
}
@@ -555,32 +555,17 @@ void Writer::createSections() {
}
}
-void Writer::calculateOffsets() {
- for (ObjFile *File : Symtab->ObjectFiles) {
- const WasmObjectFile *WasmFile = File->getWasmObj();
-
- // Function Index
- File->FunctionIndexOffset =
- FunctionImports.size() - File->NumFunctionImports() + NumFunctions;
- NumFunctions += WasmFile->functions().size();
-
- // Memory
- if (WasmFile->memories().size() > 1)
- fatal(File->getName() + ": contains more than one memory");
- }
-}
-
void Writer::calculateImports() {
for (Symbol *Sym : Symtab->getSymbols()) {
if (!Sym->isUndefined() || Sym->isWeak())
continue;
if (Sym->isFunction()) {
- Sym->setOutputIndex(FunctionImports.size());
- FunctionImports.push_back(Sym);
+ Sym->setOutputIndex(ImportedFunctions.size());
+ ImportedFunctions.push_back(Sym);
} else {
- Sym->setOutputIndex(GlobalImports.size());
- GlobalImports.push_back(Sym);
+ Sym->setOutputIndex(ImportedGlobals.size());
+ ImportedGlobals.push_back(Sym);
}
}
}
@@ -600,8 +585,9 @@ void Writer::calculateTypes() {
}
}
-void Writer::assignSymbolIndexes() {
- uint32_t GlobalIndex = GlobalImports.size();
+void Writer::assignIndexes() {
+ uint32_t GlobalIndex = ImportedGlobals.size();
+ uint32_t FunctionIndex = ImportedFunctions.size();
if (Config->StackPointerSymbol) {
DefinedGlobals.emplace_back(Config->StackPointerSymbol);
@@ -614,17 +600,15 @@ void Writer::assignSymbolIndexes() {
uint32_t TableIndex = InitialTableOffset;
for (ObjFile *File : Symtab->ObjectFiles) {
- DEBUG(dbgs() << "assignSymbolIndexes: " << File->getName() << "\n");
+ if (Config->EmitRelocs) {
+ DEBUG(dbgs() << "Globals: " << File->getName() << "\n");
+ for (Symbol *Sym : File->getSymbols()) {
+ // Create wasm globals for data symbols defined in this file
+ if (!Sym->isDefined() || File != Sym->getFile())
+ continue;
+ if (Sym->isFunction())
+ continue;
- for (Symbol *Sym : File->getSymbols()) {
- // Assign indexes for symbols defined with this file.
- if (!Sym->isDefined() || File != Sym->getFile())
- continue;
- if (Sym->isFunction()) {
- auto *Obj = cast<ObjFile>(Sym->getFile());
- Sym->setOutputIndex(Obj->FunctionIndexOffset +
- Sym->getFunctionIndex());
- } else if (Config->EmitRelocs) {
DefinedGlobals.emplace_back(Sym);
Sym->setOutputIndex(GlobalIndex++);
}
@@ -632,6 +616,15 @@ void Writer::assignSymbolIndexes() {
}
for (ObjFile *File : Symtab->ObjectFiles) {
+ DEBUG(dbgs() << "Functions: " << File->getName() << "\n");
+ for (InputFunction *Func : File->Functions) {
+ DefinedFunctions.emplace_back(Func);
+ Func->setOutputIndex(FunctionIndex++);
+ }
+ }
+
+ for (ObjFile *File : Symtab->ObjectFiles) {
+ DEBUG(dbgs() << "Table Indexes: " << File->getName() << "\n");
for (Symbol *Sym : File->getTableSymbols()) {
if (Sym->hasTableIndex() || !Sym->hasOutputIndex())
continue;
@@ -681,22 +674,20 @@ void Writer::run() {
calculateTypes();
log("-- calculateImports");
calculateImports();
- log("-- calculateOffsets");
- calculateOffsets();
+ log("-- assignIndexes");
+ assignIndexes();
if (errorHandler().Verbose) {
- log("Defined Functions: " + Twine(NumFunctions));
+ log("Defined Functions: " + Twine(DefinedFunctions.size()));
log("Defined Globals : " + Twine(DefinedGlobals.size()));
- log("Function Imports : " + Twine(FunctionImports.size()));
- log("Global Imports : " + Twine(GlobalImports.size()));
+ log("Function Imports : " + Twine(ImportedFunctions.size()));
+ log("Global Imports : " + Twine(ImportedGlobals.size()));
log("Total Imports : " +
- Twine(FunctionImports.size() + GlobalImports.size()));
+ Twine(ImportedFunctions.size() + ImportedGlobals.size()));
for (ObjFile *File : Symtab->ObjectFiles)
File->dumpInfo();
}
- log("-- assignSymbolIndexes");
- assignSymbolIndexes();
log("-- layoutMemory");
layoutMemory();
More information about the llvm-commits
mailing list