[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
diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp
index 264b106..965f5b8 100644
--- a/lld/wasm/InputFiles.cpp
+++ b/lld/wasm/InputFiles.cpp
@@ -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 @@
}
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::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::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 @@
}
// 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 @@
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 @@
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 @@
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 @@
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 @@
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() {