[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() {