[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