mirror of
https://github.com/intel/llvm.git
synced 2026-01-18 07:57:36 +08:00
[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:
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user