[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

llvm-svn: 322138
This commit is contained in:
Sam Clegg
2018-01-09 23:56:44 +00:00
parent 1f562176e9
commit 8d146bbc0c
11 changed files with 266 additions and 214 deletions

View File

@@ -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::readFile(StringRef Path) {
}
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(uint32_t Original) const {
}
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(uint32_t Original) const {
}
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 WasmSymbol &WasmSym) {
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 WasmSymbol &Sym,
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() {