[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

llvm-svn: 305769
diff --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp
index d4d978f..ad0075c 100644
--- a/llvm/tools/obj2yaml/wasm2yaml.cpp
+++ b/llvm/tools/obj2yaml/wasm2yaml.cpp
@@ -14,6 +14,7 @@
 #include "llvm/Support/YAMLTraits.h"
 
 using namespace llvm;
+using object::WasmSection;
 
 namespace {
 
@@ -22,10 +23,16 @@
 
 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 @@
   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 @@
   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 @@
 
   // 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 @@
         // 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 @@
   return Y.release();
 }
 
-} // namespace
-
 std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
   WasmDumper Dumper(Obj);
   ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();
diff --git a/llvm/tools/yaml2obj/yaml2wasm.cpp b/llvm/tools/yaml2obj/yaml2wasm.cpp
index 5c8aba3..cf591e1 100644
--- a/llvm/tools/yaml2obj/yaml2wasm.cpp
+++ b/llvm/tools/yaml2obj/yaml2wasm.cpp
@@ -26,8 +26,9 @@
 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 @@
   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 @@
   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::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);
   }