[llvm] r305769 - [WebAssembly] Add support for weak symbols in the binary format

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 19 21:05:00 PDT 2017


Author: sbc
Date: Mon Jun 19 23:04:59 2017
New Revision: 305769

URL: http://llvm.org/viewvc/llvm-project?rev=305769&view=rev
Log:
[WebAssembly] Add support for weak symbols in the binary format

This also introduces the updated format for the
"linking" section which can represent extra
symbol information.  See:
https://github.com/WebAssembly/tool-conventions/pull/10

Differential Revision: https://reviews.llvm.org/D34019

Added:
    llvm/trunk/test/ObjectYAML/wasm/weak_symbols.yaml
    llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml
Modified:
    llvm/trunk/include/llvm/BinaryFormat/Wasm.h
    llvm/trunk/include/llvm/MC/MCSymbolWasm.h
    llvm/trunk/include/llvm/Object/Wasm.h
    llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h
    llvm/trunk/lib/MC/MCWasmStreamer.cpp
    llvm/trunk/lib/MC/WasmObjectWriter.cpp
    llvm/trunk/lib/Object/WasmObjectFile.cpp
    llvm/trunk/lib/ObjectYAML/WasmYAML.cpp
    llvm/trunk/test/tools/llvm-nm/wasm/exports.yaml
    llvm/trunk/tools/obj2yaml/wasm2yaml.cpp
    llvm/trunk/tools/yaml2obj/yaml2wasm.cpp

Modified: llvm/trunk/include/llvm/BinaryFormat/Wasm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/Wasm.h?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/Wasm.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/Wasm.h Mon Jun 19 23:04:59 2017
@@ -176,6 +176,11 @@ enum class ValType {
 // Linking metadata kinds.
 enum : unsigned {
   WASM_STACK_POINTER = 0x1,
+  WASM_SYMBOL_INFO  = 0x2,
+};
+
+enum : unsigned {
+  WASM_SYMBOL_FLAG_WEAK = 0x1,
 };
 
 #define WASM_RELOC(name, value) name = value,

Modified: llvm/trunk/include/llvm/MC/MCSymbolWasm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCSymbolWasm.h?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCSymbolWasm.h (original)
+++ llvm/trunk/include/llvm/MC/MCSymbolWasm.h Mon Jun 19 23:04:59 2017
@@ -17,6 +17,7 @@ namespace llvm {
 class MCSymbolWasm : public MCSymbol {
 private:
   bool IsFunction = false;
+  bool IsWeak = false;
   std::string ModuleName;
   SmallVector<wasm::ValType, 1> Returns;
   SmallVector<wasm::ValType, 4> Params;
@@ -39,6 +40,9 @@ public:
   bool isFunction() const { return IsFunction; }
   void setIsFunction(bool isFunc) { IsFunction = isFunc; }
 
+  bool isWeak() const { return IsWeak; }
+  void setWeak(bool isWeak) { IsWeak = isWeak; }
+
   const StringRef getModuleName() const { return ModuleName; }
 
   const SmallVector<wasm::ValType, 1> &getReturns() const { return Returns; }

Modified: llvm/trunk/include/llvm/Object/Wasm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Wasm.h?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Wasm.h (original)
+++ llvm/trunk/include/llvm/Object/Wasm.h Mon Jun 19 23:04:59 2017
@@ -19,6 +19,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/BinaryFormat/Wasm.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/Object/ObjectFile.h"
@@ -48,7 +49,24 @@ public:
   StringRef Name;
   SymbolType Type;
   uint32_t Section;
+  uint32_t Flags = 0;
+
+  // Index into the imports, exports or functions array of the object depending
+  // on the type
   uint32_t ElementIndex;
+
+  bool isWeak() const {
+    return Flags & wasm::WASM_SYMBOL_FLAG_WEAK;
+  }
+
+  void print(raw_ostream &Out) const {
+    Out << "Name=" << Name << ", Type=" << static_cast<int>(Type)
+        << ", Flags=" << Flags;
+  }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
+#endif
 };
 
 class WasmSection {
@@ -63,6 +81,7 @@ public:
 };
 
 class WasmObjectFile : public ObjectFile {
+
 public:
   WasmObjectFile(MemoryBufferRef Object, Error &Err);
 
@@ -176,6 +195,7 @@ private:
 
   // Custom section types
   Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseLinkingSection(const uint8_t *Ptr, const uint8_t *End);
   Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
                           const uint8_t *End);
 
@@ -190,13 +210,22 @@ private:
   std::vector<wasm::WasmExport> Exports;
   std::vector<wasm::WasmElemSegment> ElemSegments;
   std::vector<wasm::WasmDataSegment> DataSegments;
-  std::vector<WasmSymbol> Symbols;
   std::vector<wasm::WasmFunction> Functions;
+  std::vector<WasmSymbol> Symbols;
   ArrayRef<uint8_t> CodeSection;
   uint32_t StartFunction = -1;
+
+  StringMap<uint32_t> SymbolMap;
 };
 
 } // end namespace object
+
+inline raw_ostream &operator<<(raw_ostream &OS,
+                               const object::WasmSymbol &Sym) {
+  Sym.print(OS);
+  return OS;
+}
+
 } // end namespace llvm
 
 #endif // LLVM_OBJECT_WASM_H

Modified: llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h Mon Jun 19 23:04:59 2017
@@ -112,8 +112,13 @@ struct Signature {
   ValueType ReturnType;
 };
 
+struct SymbolInfo {
+  StringRef Name;
+  uint32_t Flags;
+};
+
 struct Section {
-  Section(SectionType SecType) : Type(SecType) {}
+  explicit Section(SectionType SecType) : Type(SecType) {}
   virtual ~Section();
 
   SectionType Type;
@@ -121,20 +126,36 @@ struct Section {
 };
 
 struct CustomSection : Section {
-  CustomSection() : Section(wasm::WASM_SEC_CUSTOM) {}
+  explicit CustomSection(StringRef Name)
+      : Section(wasm::WASM_SEC_CUSTOM), Name(Name) {}
   static bool classof(const Section *S) {
     return S->Type == wasm::WASM_SEC_CUSTOM;
   }
 
   StringRef Name;
   yaml::BinaryRef Payload;
+};
+
+struct NameSection : CustomSection {
+  NameSection() : CustomSection("name") {}
+  static bool classof(const Section *S) {
+    auto C = dyn_cast<CustomSection>(S);
+    return C && C->Name == "name";
+  }
 
-  // The follow is used by the "name" custom section.
-  // TODO(sbc): Add support for more then just functions names.  The wasm
-  // name section can support multiple sub-sections.
   std::vector<NameEntry> FunctionNames;
 };
 
+struct LinkingSection : CustomSection {
+  LinkingSection() : CustomSection("linking") {}
+  static bool classof(const Section *S) {
+    auto C = dyn_cast<CustomSection>(S);
+    return C && C->Name == "linking";
+  }
+
+  std::vector<SymbolInfo> SymbolInfos;
+};
+
 struct TypeSection : Section {
   TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
   static bool classof(const Section *S) {
@@ -256,6 +277,7 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmY
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(uint32_t)
 
 namespace llvm {
@@ -329,6 +351,10 @@ template <> struct MappingTraits<WasmYAM
   static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
 };
 
+template <> struct MappingTraits<WasmYAML::SymbolInfo> {
+  static void mapping(IO &IO, WasmYAML::SymbolInfo &Info);
+};
+
 template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
   static void enumeration(IO &IO, WasmYAML::ValueType &Type);
 };

Modified: llvm/trunk/lib/MC/MCWasmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCWasmStreamer.cpp?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCWasmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCWasmStreamer.cpp Mon Jun 19 23:04:59 2017
@@ -98,18 +98,30 @@ bool MCWasmStreamer::EmitSymbolAttribute
   case MCSA_WeakDefAutoPrivate:
   case MCSA_Invalid:
   case MCSA_IndirectSymbol:
+  case MCSA_Hidden:
     return false;
+
+  case MCSA_Weak:
+  case MCSA_WeakReference:
+    Symbol->setWeak(true);
+    Symbol->setExternal(true);
+    break;
+
   case MCSA_Global:
     Symbol->setExternal(true);
     break;
+
   case MCSA_ELF_TypeFunction:
     Symbol->setIsFunction(true);
     break;
+
   case MCSA_ELF_TypeObject:
     Symbol->setIsFunction(false);
     break;
+
   default:
     // unrecognized directive
+    llvm_unreachable("unexpected MCSymbolAttr");
     return false;
   }
 

Modified: llvm/trunk/lib/MC/WasmObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/WasmObjectWriter.cpp?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/lib/MC/WasmObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/WasmObjectWriter.cpp Mon Jun 19 23:04:59 2017
@@ -156,9 +156,18 @@ struct WasmRelocationEntry {
     Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend
         << ", Type=" << Type << ", FixupSection=" << FixupSection;
   }
-  void dump() const { print(errs()); }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
+#endif
 };
 
+inline raw_ostream &operator<<(raw_ostream &OS,
+                               const WasmRelocationEntry &Rel) {
+  Rel.print(OS);
+  return OS;
+}
+
 class WasmObjectWriter : public MCObjectWriter {
   /// Helper struct for containing some precomputed information on symbols.
   struct WasmSymbolData {
@@ -229,6 +238,11 @@ private:
 
   void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
 
+  void writeString(const StringRef Str) {
+    encodeULEB128(Str.size(), getStream());
+    writeBytes(Str);
+  }
+
   void writeValueType(wasm::ValType Ty) {
     encodeSLEB128(int32_t(Ty), getStream());
   }
@@ -250,7 +264,8 @@ private:
                         uint32_t NumFuncImports);
   void writeCodeRelocSection();
   void writeDataRelocSection(uint64_t DataSectionHeaderSize);
-  void writeLinkingMetaDataSection(bool HasStackPointer,
+  void writeLinkingMetaDataSection(ArrayRef<StringRef> WeakSymbols,
+                                   bool HasStackPointer,
                                    uint32_t StackPointerGlobal);
 
   void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
@@ -282,6 +297,7 @@ void WasmObjectWriter::startSection(Sect
   assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
          "Only custom sections can have names");
 
+  DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
   encodeULEB128(SectionId, getStream());
 
   Section.SizeOffset = getStream().tell();
@@ -295,8 +311,8 @@ void WasmObjectWriter::startSection(Sect
 
   // Custom sections in wasm also have a string identifier.
   if (SectionId == wasm::WASM_SEC_CUSTOM) {
-    encodeULEB128(strlen(Name), getStream());
-    writeBytes(Name);
+    assert(Name);
+    writeString(StringRef(Name));
   }
 }
 
@@ -307,6 +323,7 @@ void WasmObjectWriter::endSection(Sectio
   if (uint32_t(Size) != Size)
     report_fatal_error("section size does not fit in a uint32_t");
 
+  DEBUG(dbgs() << "endSection size=" << Size << "\n");
   unsigned Padding = PaddingFor5ByteULEB128(Size);
 
   // Write the final section size to the payload_len field, which follows
@@ -411,6 +428,7 @@ void WasmObjectWriter::recordRelocation(
   unsigned Type = getRelocType(Target, Fixup);
 
   WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
+  DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
 
   if (FixupSection.hasInstructions())
     CodeRelocations.push_back(Rec);
@@ -455,7 +473,7 @@ static uint32_t ProvisionalValue(const W
   const MCSymbolWasm *Sym = RelEntry.Symbol;
 
   // For undefined symbols, use a hopefully invalid value.
-  if (!Sym->isDefined(false))
+  if (!Sym->isDefined(/*SetUsed=*/false))
     return UINT32_MAX;
 
   MCSectionWasm &Section =
@@ -473,17 +491,23 @@ uint32_t WasmObjectWriter::getRelocation
   switch (RelEntry.Type) {
   case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
   case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
-    assert(IndirectSymbolIndices.count(RelEntry.Symbol));
+    if (!IndirectSymbolIndices.count(RelEntry.Symbol))
+      report_fatal_error("symbol not found table index space:" +
+                         RelEntry.Symbol->getName());
     return IndirectSymbolIndices[RelEntry.Symbol];
   case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
   case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
-    assert(SymbolIndices.count(RelEntry.Symbol));
+    if (!SymbolIndices.count(RelEntry.Symbol))
+      report_fatal_error("symbol not found function/global index space:" +
+                         RelEntry.Symbol->getName());
     return SymbolIndices[RelEntry.Symbol];
   case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
-    assert(TypeIndices.count(RelEntry.Symbol));
+    if (!TypeIndices.count(RelEntry.Symbol))
+      report_fatal_error("symbol not found in type index space:" +
+                         RelEntry.Symbol->getName());
     return TypeIndices[RelEntry.Symbol];
   default:
     llvm_unreachable("invalid relocation type");
@@ -500,6 +524,7 @@ void WasmObjectWriter::applyRelocations(
                       RelEntry.FixupSection->getSectionOffset() +
                       RelEntry.Offset;
 
+    DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
     switch (RelEntry.Type) {
     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
@@ -577,6 +602,7 @@ void WasmObjectWriter::writeTypeSection(
   endSection(Section);
 }
 
+
 void WasmObjectWriter::writeImportSection(
     const SmallVector<WasmImport, 4> &Imports) {
   if (Imports.empty())
@@ -587,13 +613,8 @@ void WasmObjectWriter::writeImportSectio
 
   encodeULEB128(Imports.size(), getStream());
   for (const WasmImport &Import : Imports) {
-    StringRef ModuleName = Import.ModuleName;
-    encodeULEB128(ModuleName.size(), getStream());
-    writeBytes(ModuleName);
-
-    StringRef FieldName = Import.FieldName;
-    encodeULEB128(FieldName.size(), getStream());
-    writeBytes(FieldName);
+    writeString(Import.ModuleName);
+    writeString(Import.FieldName);
 
     encodeULEB128(Import.Kind, getStream());
 
@@ -701,11 +722,8 @@ void WasmObjectWriter::writeExportSectio
 
   encodeULEB128(Exports.size(), getStream());
   for (const WasmExport &Export : Exports) {
-    encodeULEB128(Export.FieldName.size(), getStream());
-    writeBytes(Export.FieldName);
-
+    writeString(Export.FieldName);
     encodeSLEB128(Export.Kind, getStream());
-
     encodeULEB128(Export.Index, getStream());
   }
 
@@ -750,15 +768,6 @@ void WasmObjectWriter::writeCodeSection(
     MCSectionWasm &FuncSection =
         static_cast<MCSectionWasm &>(Func.Sym->getSection());
 
-    if (Func.Sym->isVariable())
-      report_fatal_error("weak symbols not supported yet");
-
-    if (Func.Sym->getOffset() != 0)
-      report_fatal_error("function sections must contain one function each");
-
-    if (!Func.Sym->getSize())
-      report_fatal_error("function symbols must have a size set with .size");
-
     int64_t Size = 0;
     if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
       report_fatal_error(".size expression must be evaluatable");
@@ -819,15 +828,13 @@ void WasmObjectWriter::writeNameSection(
   for (const WasmImport &Import : Imports) {
     if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
       encodeULEB128(Index, getStream());
-      encodeULEB128(Import.FieldName.size(), getStream());
-      writeBytes(Import.FieldName);
+      writeString(Import.FieldName);
       ++Index;
     }
   }
   for (const WasmFunction &Func : Functions) {
     encodeULEB128(Index, getStream());
-    encodeULEB128(Func.Sym->getName().size(), getStream());
-    writeBytes(Func.Sym->getName());
+    writeString(Func.Sym->getName());
     ++Index;
   }
 
@@ -872,22 +879,37 @@ void WasmObjectWriter::writeDataRelocSec
 }
 
 void WasmObjectWriter::writeLinkingMetaDataSection(
-    bool HasStackPointer, uint32_t StackPointerGlobal) {
-  if (!HasStackPointer)
+    ArrayRef<StringRef> WeakSymbols, bool HasStackPointer,
+    uint32_t StackPointerGlobal) {
+  if (!HasStackPointer && WeakSymbols.empty())
     return;
+
   SectionBookkeeping Section;
   startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
+  SectionBookkeeping SubSection;
 
-  encodeULEB128(1, getStream()); // count
+  if (HasStackPointer) {
+    startSection(SubSection, wasm::WASM_STACK_POINTER);
+    encodeULEB128(StackPointerGlobal, getStream()); // id
+    endSection(SubSection);
+  }
 
-  encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type
-  encodeULEB128(StackPointerGlobal, getStream()); // id
+  if (WeakSymbols.size() != 0) {
+    startSection(SubSection, wasm::WASM_SYMBOL_INFO);
+    encodeULEB128(WeakSymbols.size(), getStream());
+    for (const StringRef Export: WeakSymbols) {
+      writeString(Export);
+      encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
+    }
+    endSection(SubSection);
+  }
 
   endSection(Section);
 }
 
 void WasmObjectWriter::writeObject(MCAssembler &Asm,
                                    const MCAsmLayout &Layout) {
+  DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
   MCContext &Ctx = Asm.getContext();
   wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
 
@@ -898,6 +920,7 @@ void WasmObjectWriter::writeObject(MCAss
   SmallVector<WasmGlobal, 4> Globals;
   SmallVector<WasmImport, 4> Imports;
   SmallVector<WasmExport, 4> Exports;
+  SmallVector<StringRef, 4> WeakSymbols;
   SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
   unsigned NumFuncImports = 0;
   unsigned NumGlobalImports = 0;
@@ -906,7 +929,7 @@ void WasmObjectWriter::writeObject(MCAss
   bool HasStackPointer = false;
 
   // Populate the IsAddressTaken set.
-  for (WasmRelocationEntry RelEntry : CodeRelocations) {
+  for (const WasmRelocationEntry &RelEntry : CodeRelocations) {
     switch (RelEntry.Type) {
     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
@@ -916,7 +939,7 @@ void WasmObjectWriter::writeObject(MCAss
       break;
     }
   }
-  for (WasmRelocationEntry RelEntry : DataRelocations) {
+  for (const WasmRelocationEntry &RelEntry : DataRelocations) {
     switch (RelEntry.Type) {
     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
@@ -1045,14 +1068,32 @@ void WasmObjectWriter::writeObject(MCAss
     StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
   }
 
-  // Handle defined symbols.
+  // Handle regular defined and undefined symbols.
   for (const MCSymbol &S : Asm.symbols()) {
     // Ignore unnamed temporary symbols, which aren't ever exported, imported,
     // or used in relocations.
     if (S.isTemporary() && S.getName().empty())
       continue;
+
+    // Variable references (weak references) are handled in a second pass
+    if (S.isVariable())
+      continue;
+
     const auto &WS = static_cast<const MCSymbolWasm &>(S);
+    DEBUG(dbgs() << "MCSymbol: '" << S << "'"
+                 << " isDefined=" << S.isDefined() << " isExternal="
+                 << S.isExternal() << " isTemporary=" << S.isTemporary()
+                 << " isFunction=" << WS.isFunction()
+                 << " isWeak=" << WS.isWeak()
+                 << " isVariable=" << WS.isVariable() << "\n");
+
+    if (WS.isWeak())
+      WeakSymbols.push_back(WS.getName());
+
     unsigned Index;
+
+                 //<< " function=" << S.isFunction()
+
     if (WS.isFunction()) {
       // Prepare the function's type, if we haven't seen it yet.
       WasmFunctionType F;
@@ -1066,6 +1107,14 @@ void WasmObjectWriter::writeObject(MCAss
       int32_t Type = Pair.first->second;
 
       if (WS.isDefined(/*SetUsed=*/false)) {
+        if (WS.getOffset() != 0)
+          report_fatal_error(
+              "function sections must contain one function each");
+
+        if (WS.getSize() == 0)
+          report_fatal_error(
+              "function symbols must have a size set with .size");
+
         // A definition. Take the next available index.
         Index = NumFuncImports + Functions.size();
 
@@ -1076,6 +1125,9 @@ void WasmObjectWriter::writeObject(MCAss
         SymbolIndices[&WS] = Index;
         Functions.push_back(Func);
       } else {
+        // Should be no such thing as weak undefined symbol
+        assert(!WS.isVariable());
+
         // An import; the index was assigned above.
         Index = SymbolIndices.find(&WS)->second;
       }
@@ -1089,7 +1141,7 @@ void WasmObjectWriter::writeObject(MCAss
       if (WS.isTemporary() && !WS.getSize())
         continue;
 
-      if (WS.isDefined(false)) {
+      if (WS.isDefined(/*SetUsed=*/false)) {
         if (WS.getOffset() != 0)
           report_fatal_error("data sections must contain one variable each: " +
                              WS.getName());
@@ -1154,21 +1206,46 @@ void WasmObjectWriter::writeObject(MCAss
     }
 
     // If the symbol is visible outside this translation unit, export it.
-    if (WS.isExternal()) {
-      assert(WS.isDefined(false));
+    if (WS.isExternal() && WS.isDefined(/*SetUsed=*/false)) {
       WasmExport Export;
       Export.FieldName = WS.getName();
       Export.Index = Index;
-
       if (WS.isFunction())
         Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
       else
         Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
-
       Exports.push_back(Export);
     }
   }
 
+  // Handle weak aliases
+  for (const MCSymbol &S : Asm.symbols()) {
+    if (!S.isVariable())
+      continue;
+    assert(S.isExternal());
+    assert(S.isDefined(/*SetUsed=*/false));
+
+    const auto &WS = static_cast<const MCSymbolWasm &>(S);
+
+    // Find the target symbol of this weak alias
+    const MCExpr *Expr = WS.getVariableValue();
+    auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
+    const MCSymbolWasm *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
+    uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
+    DEBUG(dbgs() << "Weak alias: '" << WS << "' -> '" << ResolvedSym << "' = " << Index << "\n");
+    SymbolIndices[&WS] = Index;
+
+    WasmExport Export;
+    Export.FieldName = WS.getName();
+    Export.Index = Index;
+    if (WS.isFunction())
+      Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
+    else
+      Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
+    WeakSymbols.push_back(Export.FieldName);
+    Exports.push_back(Export);
+  }
+
   // Add types for indirect function calls.
   for (const WasmRelocationEntry &Fixup : CodeRelocations) {
     if (Fixup.Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
@@ -1202,7 +1279,7 @@ void WasmObjectWriter::writeObject(MCAss
   writeNameSection(Functions, Imports, NumFuncImports);
   writeCodeRelocSection();
   writeDataRelocSection(DataSectionHeaderSize);
-  writeLinkingMetaDataSection(HasStackPointer, StackPointerGlobal);
+  writeLinkingMetaDataSection(WeakSymbols, HasStackPointer, StackPointerGlobal);
 
   // TODO: Translate the .comment section to the output.
   // TODO: Translate debug sections to the output.

Modified: llvm/trunk/lib/Object/WasmObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/WasmObjectFile.cpp?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/lib/Object/WasmObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/WasmObjectFile.cpp Mon Jun 19 23:04:59 2017
@@ -28,6 +28,8 @@
 #include <cstring>
 #include <system_error>
 
+#define DEBUG_TYPE "wasm-object"
+
 using namespace llvm;
 using namespace object;
 
@@ -256,6 +258,7 @@ Error WasmObjectFile::parseNameSection(c
   while (Ptr < End) {
     uint8_t Type = readVarint7(Ptr);
     uint32_t Size = readVaruint32(Ptr);
+    const uint8_t *SubSectionEnd = Ptr + Size;
     switch (Type) {
     case wasm::WASM_NAMES_FUNCTION: {
       uint32_t Count = readVaruint32(Ptr);
@@ -275,6 +278,9 @@ Error WasmObjectFile::parseNameSection(c
       Ptr += Size;
       break;
     }
+    if (Ptr != SubSectionEnd)
+      return make_error<GenericBinaryError>("Name sub-section ended prematurely",
+                                            object_error::parse_failed);
   }
 
   if (Ptr != End)
@@ -283,6 +289,50 @@ Error WasmObjectFile::parseNameSection(c
   return Error::success();
 }
 
+Error WasmObjectFile::parseLinkingSection(const uint8_t *Ptr,
+                                          const uint8_t *End) {
+  while (Ptr < End) {
+    uint8_t Type = readVarint7(Ptr);
+    uint32_t Size = readVaruint32(Ptr);
+    const uint8_t *SubSectionEnd = Ptr + Size;
+    switch (Type) {
+    case wasm::WASM_SYMBOL_INFO: {
+      uint32_t Count = readVaruint32(Ptr);
+      while (Count--) {
+        StringRef Symbol = readString(Ptr);
+        DEBUG(dbgs() << "reading syminfo: " << Symbol << "\n");
+        uint32_t Flags = readVaruint32(Ptr);
+        auto iter = SymbolMap.find(Symbol);
+        if (iter == SymbolMap.end()) {
+          return make_error<GenericBinaryError>(
+              "Invalid symbol name in linking section",
+              object_error::parse_failed);
+        }
+        uint32_t SymIndex = iter->second;
+        assert(SymIndex < Symbols.size());
+        Symbols[SymIndex].Flags = Flags;
+        DEBUG(dbgs() << "Set symbol flags index:"
+                     << SymIndex << " name:"
+                     << Symbols[SymIndex].Name << " exptected:"
+                     << Symbol << " flags: " << Flags << "\n");
+      }
+      break;
+    }
+    case wasm::WASM_STACK_POINTER:
+    default:
+      Ptr += Size;
+      break;
+    }
+    if (Ptr != SubSectionEnd)
+      return make_error<GenericBinaryError>(
+          "Linking sub-section ended prematurely", object_error::parse_failed);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Linking section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
 WasmSection* WasmObjectFile::findCustomSectionByName(StringRef Name) {
   for (WasmSection& Section : Sections) {
     if (Section.Type == wasm::WASM_SEC_CUSTOM && Section.Name == Name)
@@ -351,6 +401,9 @@ Error WasmObjectFile::parseCustomSection
   if (Sec.Name == "name") {
     if (Error Err = parseNameSection(Ptr, End))
       return Err;
+  } else if (Sec.Name == "linking") {
+    if (Error Err = parseLinkingSection(Ptr, End))
+      return Err;
   } else if (Sec.Name.startswith("reloc.")) {
     if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
       return Err;
@@ -402,14 +455,20 @@ Error WasmObjectFile::parseImportSection
     switch (Im.Kind) {
     case wasm::WASM_EXTERNAL_FUNCTION:
       Im.SigIndex = readVaruint32(Ptr);
+      SymbolMap.try_emplace(Im.Field, Symbols.size());
       Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT,
                            Sections.size(), i);
+      DEBUG(dbgs() << "Adding import: " << Symbols.back()
+                   << " sym index:" << Symbols.size() << "\n");
       break;
     case wasm::WASM_EXTERNAL_GLOBAL:
       Im.Global.Type = readVarint7(Ptr);
       Im.Global.Mutable = readVaruint1(Ptr);
+      SymbolMap.try_emplace(Im.Field, Symbols.size());
       Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT,
                            Sections.size(), i);
+      DEBUG(dbgs() << "Adding import: " << Symbols.back()
+                   << " sym index:" << Symbols.size() << "\n");
       break;
     case wasm::WASM_EXTERNAL_MEMORY:
       Im.Memory = readLimits(Ptr);
@@ -498,15 +557,20 @@ Error WasmObjectFile::parseExportSection
     Ex.Name = readString(Ptr);
     Ex.Kind = readUint8(Ptr);
     Ex.Index = readVaruint32(Ptr);
-    Exports.push_back(Ex);
     switch (Ex.Kind) {
     case wasm::WASM_EXTERNAL_FUNCTION:
+      SymbolMap.try_emplace(Ex.Name, Symbols.size());
       Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT,
                            Sections.size(), i);
+      DEBUG(dbgs() << "Adding export: " << Symbols.back()
+                   << " sym index:" << Symbols.size() << "\n");
       break;
     case wasm::WASM_EXTERNAL_GLOBAL:
+      SymbolMap.try_emplace(Ex.Name, Symbols.size());
       Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT,
                            Sections.size(), i);
+      DEBUG(dbgs() << "Adding export: " << Symbols.back()
+                   << " sym index:" << Symbols.size() << "\n");
       break;
     case wasm::WASM_EXTERNAL_MEMORY:
     case wasm::WASM_EXTERNAL_TABLE:
@@ -515,6 +579,7 @@ Error WasmObjectFile::parseExportSection
       return make_error<GenericBinaryError>(
           "Unexpected export kind", object_error::parse_failed);
     }
+    Exports.push_back(Ex);
   }
   if (Ptr != End)
     return make_error<GenericBinaryError>("Export section ended prematurely",
@@ -622,6 +687,10 @@ uint32_t WasmObjectFile::getSymbolFlags(
   uint32_t Result = SymbolRef::SF_None;
   const WasmSymbol &Sym = getWasmSymbol(Symb);
 
+  DEBUG(dbgs() << "getSymbolFlags: ptr=" << &Sym << " " << Sym << "\n");
+  if (Sym.Flags & wasm::WASM_SYMBOL_FLAG_WEAK)
+    Result |= SymbolRef::SF_Weak;
+
   switch (Sym.Type) {
   case WasmSymbol::SymbolType::FUNCTION_IMPORT:
     Result |= SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
@@ -631,6 +700,7 @@ uint32_t WasmObjectFile::getSymbolFlags(
     break;
   case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
     Result |= SymbolRef::SF_Executable;
+    Result |= SymbolRef::SF_FormatSpecific;
     break;
   case WasmSymbol::SymbolType::GLOBAL_IMPORT:
     Result |= SymbolRef::SF_Undefined;
@@ -664,8 +734,7 @@ const WasmSymbol &WasmObjectFile::getWas
 }
 
 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
-  const WasmSymbol &Sym = getWasmSymbol(Symb);
-  return Sym.Name;
+  return getWasmSymbol(Symb).Name;
 }
 
 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
@@ -673,8 +742,17 @@ Expected<uint64_t> WasmObjectFile::getSy
 }
 
 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
-  const WasmSymbol &Sym = getWasmSymbol(Symb);
-  return Sym.ElementIndex;
+  const WasmSymbol& Sym = getWasmSymbol(Symb);
+  switch (Sym.Type) {
+  case WasmSymbol::SymbolType::FUNCTION_IMPORT:
+  case WasmSymbol::SymbolType::GLOBAL_IMPORT:
+    return 0;
+  case WasmSymbol::SymbolType::FUNCTION_EXPORT:
+  case WasmSymbol::SymbolType::GLOBAL_EXPORT:
+    return Exports[Sym.ElementIndex].Index;
+  case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
+    return Sym.ElementIndex;
+  }
 }
 
 uint32_t WasmObjectFile::getSymbolAlignment(DataRefImpl Symb) const {

Modified: llvm/trunk/lib/ObjectYAML/WasmYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/WasmYAML.cpp?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/WasmYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/WasmYAML.cpp Mon Jun 19 23:04:59 2017
@@ -47,14 +47,22 @@ static void commonSectionMapping(IO &IO,
   IO.mapOptional("Relocations", Section.Relocations);
 }
 
+static void sectionMapping(IO &IO, WasmYAML::NameSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapRequired("Name", Section.Name);
+  IO.mapOptional("FunctionNames", Section.FunctionNames);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapRequired("Name", Section.Name);
+  IO.mapRequired("SymbolInfo", Section.SymbolInfos);
+}
+
 static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
   commonSectionMapping(IO, Section);
   IO.mapRequired("Name", Section.Name);
-  if (Section.Name == "name") {
-    IO.mapOptional("FunctionNames", Section.FunctionNames);
-  } else {
-    IO.mapRequired("Payload", Section.Payload);
-  }
+  IO.mapRequired("Payload", Section.Payload);
 }
 
 static void sectionMapping(IO &IO, WasmYAML::TypeSection &Section) {
@@ -121,11 +129,29 @@ void MappingTraits<std::unique_ptr<WasmY
     IO.mapRequired("Type", SectionType);
 
   switch (SectionType) {
-  case wasm::WASM_SEC_CUSTOM:
-    if (!IO.outputting())
-      Section.reset(new WasmYAML::CustomSection());
-    sectionMapping(IO, *cast<WasmYAML::CustomSection>(Section.get()));
+  case wasm::WASM_SEC_CUSTOM: {
+    StringRef SectionName;
+    if (IO.outputting()) {
+      auto CustomSection = cast<WasmYAML::CustomSection>(Section.get());
+      SectionName = CustomSection->Name;
+    } else {
+      IO.mapRequired("Name", SectionName);
+    }
+    if (SectionName == "linking") {
+      if (!IO.outputting())
+        Section.reset(new WasmYAML::LinkingSection());
+      sectionMapping(IO, *cast<WasmYAML::LinkingSection>(Section.get()));
+    } else if (SectionName == "name") {
+      if (!IO.outputting())
+        Section.reset(new WasmYAML::NameSection());
+      sectionMapping(IO, *cast<WasmYAML::NameSection>(Section.get()));
+    } else {
+      if (!IO.outputting())
+        Section.reset(new WasmYAML::CustomSection(SectionName));
+      sectionMapping(IO, *cast<WasmYAML::CustomSection>(Section.get()));
+    }
     break;
+  }
   case wasm::WASM_SEC_TYPE:
     if (!IO.outputting())
       Section.reset(new WasmYAML::TypeSection());
@@ -321,6 +347,12 @@ void MappingTraits<WasmYAML::DataSegment
   IO.mapRequired("Content", Segment.Content);
 }
 
+void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
+                                                  WasmYAML::SymbolInfo &Info) {
+  IO.mapRequired("Name", Info.Name);
+  IO.mapRequired("Flags", Info.Flags);
+}
+
 void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
     IO &IO, WasmYAML::ValueType &Type) {
 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);

Added: llvm/trunk/test/ObjectYAML/wasm/weak_symbols.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/weak_symbols.yaml?rev=305769&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/weak_symbols.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/weak_symbols.yaml Mon Jun 19 23:04:59 2017
@@ -0,0 +1,40 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            EXPORT
+    Exports:         
+      - Name:            function_export
+        Kind:            FUNCTION
+        Index:           1
+      - Name:            global_export
+        Kind:            GLOBAL
+        Index:           2
+  - Type:            CUSTOM
+    Name:            linking
+    SymbolInfo:
+      - Name:            function_export
+        Flags:           1
+      - Name:            global_export
+        Flags:           1
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:   - Type:            EXPORT
+# CHECK:     Exports:         
+# CHECK:       - Name:            function_export
+# CHECK:         Kind:            FUNCTION
+# CHECK:         Index:           1
+# CHECK:       - Name:            global_export
+# CHECK:         Kind:            GLOBAL
+# CHECK:         Index:           2
+# CHECK:   - Type:            CUSTOM
+# CHECK:     Name:            linking
+# CHECK:     SymbolInfo:
+# CHECK:       - Name:            function_export
+# CHECK:         Flags:           1
+# CHECK:       - Name:            global_export
+# CHECK:         Flags:           1

Modified: llvm/trunk/test/tools/llvm-nm/wasm/exports.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-nm/wasm/exports.yaml?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-nm/wasm/exports.yaml (original)
+++ llvm/trunk/test/tools/llvm-nm/wasm/exports.yaml Mon Jun 19 23:04:59 2017
@@ -1,5 +1,8 @@
 # RUN: yaml2obj < %s | llvm-nm - | FileCheck %s
 
+# That wasm exports of functions and globals are displayed as global data and
+# code symbols.
+
 --- !WASM
 FileHeader:
   Version:         0x00000001
@@ -13,10 +16,10 @@ Sections:
     Exports:
       - Name:            foo
         Kind:            FUNCTION
-        Index:           0x00000000
+        Index:           0x00000004
       - Name:            bar
         Kind:            GLOBAL
-        Index:           0x00000000
+        Index:           0x00000002
 
-# CHECK: 00000001 D bar
-# CHECK: 00000000 T foo
+# CHECK: 00000002 D bar
+# CHECK: 00000004 T foo

Added: llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml?rev=305769&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml (added)
+++ llvm/trunk/test/tools/llvm-nm/wasm/weak-symbols.yaml Mon Jun 19 23:04:59 2017
@@ -0,0 +1,49 @@
+# RUN: yaml2obj < %s | llvm-nm - | FileCheck %s
+
+# That wasm exports of functions and globals are displayed as global data and
+# code symbols.
+
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - ReturnType:      I32
+        ParamTypes:
+          - I32
+  - Type:            IMPORT
+    Imports:
+      - Module:          env
+        Field:           weak_import_func
+        Kind:            FUNCTION
+        SigIndex:        0
+      - Module:          env
+        Field:           weak_import_data
+        Kind:            GLOBAL
+        GlobalType:      I32
+        GlobalMutable:   false
+  - Type:            EXPORT
+    Exports:
+      - Name:            weak_global_func
+        Kind:            FUNCTION
+        Index:           0x00000004
+      - Name:            weak_global_data
+        Kind:            GLOBAL
+        Index:           0x00000002
+  - Type:            CUSTOM
+    Name:            linking
+    SymbolInfo:
+      - Name:            weak_global_func
+        Flags:           1
+      - Name:            weak_global_data
+        Flags:           1
+      - Name:            weak_import_func
+        Flags:           1
+      - Name:            weak_import_data
+        Flags:           1
+
+# CHECK: 00000002 W weak_global_data
+# CHECK: 00000004 W weak_global_func
+# CHECK:          w weak_import_data
+# CHECK:          w weak_import_func

Modified: llvm/trunk/tools/obj2yaml/wasm2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/wasm2yaml.cpp?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/wasm2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/wasm2yaml.cpp Mon Jun 19 23:04:59 2017
@@ -14,6 +14,7 @@
 #include "llvm/Support/YAMLTraits.h"
 
 using namespace llvm;
+using object::WasmSection;
 
 namespace {
 
@@ -22,10 +23,16 @@ class WasmDumper {
 
 public:
   WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
+
   ErrorOr<WasmYAML::Object *> dump();
+
+  std::unique_ptr<WasmYAML::CustomSection>
+  dumpCustomSection(const WasmSection &WasmSec);
 };
 
-WasmYAML::Table make_table(const wasm::WasmTable &Table) {
+} // namespace
+
+static WasmYAML::Table make_table(const wasm::WasmTable &Table) {
   WasmYAML::Table T;
   T.ElemType = Table.ElemType;
   T.TableLimits.Flags = Table.Limits.Flags;
@@ -34,7 +41,7 @@ WasmYAML::Table make_table(const wasm::W
   return T;
 }
 
-WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
+static WasmYAML::Limits make_limits(const wasm::WasmLimits &Limits) {
   WasmYAML::Limits L;
   L.Flags = Limits.Flags;
   L.Initial = Limits.Initial;
@@ -42,6 +49,42 @@ WasmYAML::Limits make_limits(const wasm:
   return L;
 }
 
+std::unique_ptr<WasmYAML::CustomSection> WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
+  std::unique_ptr<WasmYAML::CustomSection> CustomSec;
+  if (WasmSec.Name == "name") {
+    std::unique_ptr<WasmYAML::NameSection> NameSec = make_unique<WasmYAML::NameSection>();
+    for (const object::SymbolRef& Sym: Obj.symbols()) {
+      uint32_t Flags = Sym.getFlags();
+      // Skip over symbols that come from imports or exports
+      if (Flags &
+          (object::SymbolRef::SF_Global | object::SymbolRef::SF_Undefined))
+        continue;
+      Expected<StringRef> NameOrError = Sym.getName();
+      if (!NameOrError)
+        continue;
+      WasmYAML::NameEntry NameEntry;
+      NameEntry.Name = *NameOrError;
+      NameEntry.Index = Sym.getValue();
+      NameSec->FunctionNames.push_back(NameEntry);
+    }
+    CustomSec = std::move(NameSec);
+  } else if (WasmSec.Name == "linking") {
+    std::unique_ptr<WasmYAML::LinkingSection> LinkingSec = make_unique<WasmYAML::LinkingSection>();
+    for (const object::SymbolRef& Sym: Obj.symbols()) {
+      const object::WasmSymbol Symbol = Obj.getWasmSymbol(Sym);
+      if (Symbol.Flags != 0) {
+        WasmYAML::SymbolInfo Info = { Symbol.Name, Symbol.Flags };
+        LinkingSec->SymbolInfos.push_back(Info);
+      }
+    }
+    CustomSec = std::move(LinkingSec);
+  } else {
+    CustomSec = make_unique<WasmYAML::CustomSection>(WasmSec.Name);
+  }
+  CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
+  return CustomSec;
+}
+
 ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
   auto Y = make_unique<WasmYAML::Object>();
 
@@ -50,7 +93,7 @@ ErrorOr<WasmYAML::Object *> WasmDumper::
 
   // Dump sections
   for (const auto &Sec : Obj.sections()) {
-    const object::WasmSection &WasmSec = Obj.getWasmSection(Sec);
+    const WasmSection &WasmSec = Obj.getWasmSection(Sec);
     std::unique_ptr<WasmYAML::Section> S;
     switch (WasmSec.Type) {
     case wasm::WASM_SEC_CUSTOM: {
@@ -59,27 +102,7 @@ ErrorOr<WasmYAML::Object *> WasmDumper::
         // being represented as a custom section in the YAML output.
         continue;
       }
-      auto CustomSec = make_unique<WasmYAML::CustomSection>();
-      CustomSec->Name = WasmSec.Name;
-      if (CustomSec->Name == "name") {
-        for (const object::SymbolRef& Sym: Obj.symbols()) {
-          uint32_t Flags = Sym.getFlags();
-          // Skip over symbols that come from imports or exports
-          if (Flags &
-              (object::SymbolRef::SF_Global | object::SymbolRef::SF_Undefined))
-            continue;
-          Expected<StringRef> NameOrError = Sym.getName();
-          if (!NameOrError)
-            continue;
-          WasmYAML::NameEntry NameEntry;
-          NameEntry.Name = *NameOrError;
-          NameEntry.Index = Sym.getValue();
-          CustomSec->FunctionNames.push_back(NameEntry);
-        }
-      } else {
-        CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
-      }
-      S = std::move(CustomSec);
+      S = dumpCustomSection(WasmSec);
       break;
     }
     case wasm::WASM_SEC_TYPE: {
@@ -237,8 +260,6 @@ ErrorOr<WasmYAML::Object *> WasmDumper::
   return Y.release();
 }
 
-} // namespace
-
 std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
   WasmDumper Dumper(Obj);
   ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();

Modified: llvm/trunk/tools/yaml2obj/yaml2wasm.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2wasm.cpp?rev=305769&r1=305768&r2=305769&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2wasm.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2wasm.cpp Mon Jun 19 23:04:59 2017
@@ -26,8 +26,9 @@ class WasmWriter {
 public:
   WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
   int writeWasm(raw_ostream &OS);
+
+private:
   int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec);
-  int writeNameSection(raw_ostream &OS, WasmYAML::CustomSection &Section);
 
   int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
   int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
@@ -42,7 +43,9 @@ public:
   int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
   int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
 
-private:
+  // Custom section types
+  int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
   WasmYAML::Object &Obj;
 };
 
@@ -107,12 +110,30 @@ static int writeInitExpr(const wasm::Was
   return 0;
 }
 
-int WasmWriter::writeNameSection(raw_ostream &OS,
-                                 WasmYAML::CustomSection &Section) {
+int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
+  writeStringRef(Section.Name, OS);
+  if (Section.SymbolInfos.size()) {
+    encodeULEB128(wasm::WASM_SYMBOL_INFO, OS);
+    std::string OutString;
+    raw_string_ostream StringStream(OutString);
+
+    encodeULEB128(Section.SymbolInfos.size(), StringStream);
+    for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) {
+      writeStringRef(Info.Name, StringStream);
+      encodeULEB128(Info.Flags, StringStream);
+    }
+
+    StringStream.flush();
+    encodeULEB128(OutString.size(), OS);
+    OS << OutString;
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) {
   writeStringRef(Section.Name, OS);
   if (Section.FunctionNames.size()) {
     encodeULEB128(wasm::WASM_NAMES_FUNCTION, OS);
-
     std::string OutString;
     raw_string_ostream StringStream(OutString);
 
@@ -131,8 +152,12 @@ int WasmWriter::writeNameSection(raw_ost
 
 int WasmWriter::writeSectionContent(raw_ostream &OS,
                                     WasmYAML::CustomSection &Section) {
-  if (Section.Name == "name") {
-    writeNameSection(OS, Section);
+  if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
+    if (auto Err = writeSectionContent(OS, *S))
+      return Err;
+  } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
+    if (auto Err = writeSectionContent(OS, *S))
+      return Err;
   } else {
     Section.Payload.writeAsBinary(OS);
   }




More information about the llvm-commits mailing list