[llvm] r299101 - [WebAssembly] Improve support for WebAssembly binary format

Derek Schuff via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 30 12:44:10 PDT 2017


Author: dschuff
Date: Thu Mar 30 14:44:09 2017
New Revision: 299101

URL: http://llvm.org/viewvc/llvm-project?rev=299101&view=rev
Log:
[WebAssembly] Improve support for WebAssembly binary format

Mostly this change adds support converting to and from
YAML which will allow us to write more test cases for
the WebAssembly MC and lld ports.

Better support for objdump, readelf, and nm will be in
followup CLs.

I had to update the two wasm test binaries because they
used the old style 'name' section which is no longer
supported.

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

Patch by Sam Clegg

Added:
    llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h
    llvm/trunk/lib/ObjectYAML/WasmYAML.cpp
    llvm/trunk/test/ObjectYAML/wasm/
    llvm/trunk/test/ObjectYAML/wasm/code_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/custom_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/data_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/elem_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/export_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/function_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/global_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/header.yaml
    llvm/trunk/test/ObjectYAML/wasm/header_invalid_version.yaml
    llvm/trunk/test/ObjectYAML/wasm/import_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/memory_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/start_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/table_section.yaml
    llvm/trunk/test/ObjectYAML/wasm/type_section.yaml
    llvm/trunk/tools/obj2yaml/wasm2yaml.cpp
    llvm/trunk/tools/yaml2obj/yaml2wasm.cpp
Modified:
    llvm/trunk/include/llvm/Object/Wasm.h
    llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h
    llvm/trunk/include/llvm/Support/Wasm.h
    llvm/trunk/lib/Object/WasmObjectFile.cpp
    llvm/trunk/lib/ObjectYAML/CMakeLists.txt
    llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp
    llvm/trunk/test/tools/llvm-objdump/Inputs/test.wasm
    llvm/trunk/test/tools/llvm-objdump/wasm.txt
    llvm/trunk/test/tools/llvm-readobj/Inputs/trivial.obj.wasm
    llvm/trunk/test/tools/llvm-readobj/sections.test
    llvm/trunk/tools/llvm-readobj/WasmDumper.cpp
    llvm/trunk/tools/obj2yaml/CMakeLists.txt
    llvm/trunk/tools/obj2yaml/obj2yaml.cpp
    llvm/trunk/tools/obj2yaml/obj2yaml.h
    llvm/trunk/tools/yaml2obj/CMakeLists.txt
    llvm/trunk/tools/yaml2obj/yaml2obj.cpp
    llvm/trunk/tools/yaml2obj/yaml2obj.h

Modified: llvm/trunk/include/llvm/Object/Wasm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Wasm.h?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Wasm.h (original)
+++ llvm/trunk/include/llvm/Object/Wasm.h Thu Mar 30 14:44:09 2017
@@ -29,21 +29,64 @@
 namespace llvm {
 namespace object {
 
+class WasmSymbol {
+public:
+  enum class SymbolType {
+    FUNCTION_IMPORT,
+    FUNCTION_EXPORT,
+    GLOBAL_IMPORT,
+    GLOBAL_EXPORT,
+    DEBUG_FUNCTION_NAME,
+  };
+
+  WasmSymbol(StringRef Name, SymbolType Type) : Name(Name), Type(Type) {}
+
+  StringRef Name;
+  SymbolType Type;
+};
+
+class WasmSection {
+public:
+  WasmSection() : Type(0), Offset(0) {}
+
+  uint32_t Type; // Section type (See below)
+  uint32_t Offset; // Offset with in the file
+  StringRef Name; // Section name (User-defined sections only)
+  ArrayRef<uint8_t> Content; // Section content
+  std::vector<wasm::WasmRelocation> Relocations; // Relocations for this section
+};
+
 class WasmObjectFile : public ObjectFile {
 public:
   WasmObjectFile(MemoryBufferRef Object, Error &Err);
 
   const wasm::WasmObjectHeader &getHeader() const;
-  const wasm::WasmSection *getWasmSection(const SectionRef &Section) const;
+  const WasmSymbol &getWasmSymbol(DataRefImpl Symb) const;
+  const WasmSection &getWasmSection(const SectionRef &Section) const;
+  const wasm::WasmRelocation &getWasmRelocation(const RelocationRef& Ref) const;
 
   static bool classof(const Binary *v) { return v->isWasm(); }
 
+  const std::vector<wasm::WasmSignature>& types() const { return Signatures; }
+  const std::vector<uint32_t>& functionTypes() const { return FunctionTypes; }
+  const std::vector<wasm::WasmImport>& imports() const { return Imports; }
+  const std::vector<wasm::WasmTable>& tables() const { return Tables; }
+  const std::vector<wasm::WasmLimits>& memories() const { return Memories; }
+  const std::vector<wasm::WasmGlobal>& globals() const { return Globals; }
+  const std::vector<wasm::WasmExport>& exports() const { return Exports; }
+  const std::vector<wasm::WasmElemSegment>& elements() const {
+    return ElemSegments;
+  }
+  const std::vector<wasm::WasmDataSegment>& dataSegments() const {
+    return DataSegments;
+  }
+  const std::vector<wasm::WasmFunction>& functions() const { return Functions; }
+  const ArrayRef<uint8_t>& code() const { return CodeSection; }
+  uint32_t startFunction() const { return StartFunction; }
+
 protected:
   void moveSymbolNext(DataRefImpl &Symb) const override;
 
-  std::error_code printSymbolName(raw_ostream &OS,
-                                  DataRefImpl Symb) const override;
-
   uint32_t getSymbolFlags(DataRefImpl Symb) const override;
 
   basic_symbol_iterator symbol_begin() const override;
@@ -75,7 +118,6 @@ protected:
   bool isSectionBitcode(DataRefImpl Sec) const override;
   relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
   relocation_iterator section_rel_end(DataRefImpl Sec) const override;
-  section_iterator getRelocatedSection(DataRefImpl Sec) const override;
 
   // Overrides from RelocationRef.
   void moveRelocationNext(DataRefImpl &Rel) const override;
@@ -94,12 +136,50 @@ protected:
   bool isRelocatableObject() const override;
 
 private:
+  const WasmSection &getWasmSection(DataRefImpl Ref) const;
+  const wasm::WasmRelocation &getWasmRelocation(DataRefImpl Ref) const;
+
+  WasmSection* findCustomSectionByName(StringRef Name);
+  WasmSection* findSectionByType(uint32_t Type);
+
   const uint8_t *getPtr(size_t Offset) const;
-  Error parseCustomSection(wasm::WasmSection &Sec, const uint8_t *Ptr,
-                           size_t Length);
+  Error parseSection(WasmSection &Sec);
+  Error parseCustomSection(WasmSection &Sec, const uint8_t *Ptr,
+                           const uint8_t *End);
+
+  // Standard section types
+  Error parseTypeSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseImportSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseFunctionSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseTableSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseMemorySection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseGlobalSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseExportSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseStartSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseElemSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseCodeSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseDataSection(const uint8_t *Ptr, const uint8_t *End);
+
+  // Custom section types
+  Error parseNameSection(const uint8_t *Ptr, const uint8_t *End);
+  Error parseRelocSection(StringRef Name, const uint8_t *Ptr,
+                          const uint8_t *End);
 
   wasm::WasmObjectHeader Header;
-  std::vector<wasm::WasmSection> Sections;
+  std::vector<WasmSection> Sections;
+  std::vector<wasm::WasmSignature> Signatures;
+  std::vector<uint32_t> FunctionTypes;
+  std::vector<wasm::WasmTable> Tables;
+  std::vector<wasm::WasmLimits> Memories;
+  std::vector<wasm::WasmGlobal> Globals;
+  std::vector<wasm::WasmImport> Imports;
+  std::vector<wasm::WasmExport> Exports;
+  std::vector<wasm::WasmElemSegment> ElemSegments;
+  std::vector<wasm::WasmDataSegment> DataSegments;
+  std::vector<WasmSymbol> Symbols;
+  std::vector<wasm::WasmFunction> Functions;
+  ArrayRef<uint8_t> CodeSection;
+  uint32_t StartFunction;
 };
 
 } // end namespace object

Modified: llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h (original)
+++ llvm/trunk/include/llvm/ObjectYAML/ObjectYAML.h Thu Mar 30 14:44:09 2017
@@ -10,10 +10,11 @@
 #ifndef LLVM_OBJECTYAML_OBJECTYAML_H
 #define LLVM_OBJECTYAML_OBJECTYAML_H
 
-#include "llvm/Support/YAMLTraits.h"
-#include "llvm/ObjectYAML/ELFYAML.h"
 #include "llvm/ObjectYAML/COFFYAML.h"
+#include "llvm/ObjectYAML/ELFYAML.h"
 #include "llvm/ObjectYAML/MachOYAML.h"
+#include "llvm/ObjectYAML/WasmYAML.h"
+#include "llvm/Support/YAMLTraits.h"
 
 namespace llvm {
 namespace yaml {
@@ -23,6 +24,7 @@ struct YamlObjectFile {
   std::unique_ptr<COFFYAML::Object> Coff;
   std::unique_ptr<MachOYAML::Object> MachO;
   std::unique_ptr<MachOYAML::UniversalBinary> FatMachO;
+  std::unique_ptr<WasmYAML::Object> Wasm;
 };
 
 template <> struct MappingTraits<YamlObjectFile> {

Added: llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h?rev=299101&view=auto
==============================================================================
--- llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h (added)
+++ llvm/trunk/include/llvm/ObjectYAML/WasmYAML.h Thu Mar 30 14:44:09 2017
@@ -0,0 +1,338 @@
+//===- WasmYAML.h - Wasm YAMLIO implementation ------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file declares classes for handling the YAML representation
+/// of wasm binaries.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECTYAML_WASMYAML_H
+#define LLVM_OBJECTYAML_WASMYAML_H
+
+#include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Wasm.h"
+
+namespace llvm {
+namespace WasmYAML {
+
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, ValueType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, TableType)
+LLVM_YAML_STRONG_TYPEDEF(int32_t, SignatureForm)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportKind)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, Opcode)
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType)
+
+struct FileHeader {
+  yaml::Hex32 Version;
+};
+
+struct Import {
+  StringRef Module;
+  StringRef Field;
+  ExportKind Kind;
+  union {
+    uint32_t SigIndex;
+    ValueType GlobalType;
+  };
+  bool GlobalMutable;
+};
+
+struct Limits {
+  yaml::Hex32 Flags;
+  yaml::Hex32 Initial;
+  yaml::Hex32 Maximum;
+};
+
+struct Table {
+  TableType ElemType;
+  Limits TableLimits;
+};
+
+struct Export {
+  StringRef Name;
+  ExportKind Kind;
+  uint32_t Index;
+};
+
+struct ElemSegment {
+  uint32_t TableIndex;
+  wasm::WasmInitExpr Offset;
+  std::vector<uint32_t> Functions;
+};
+
+struct Global {
+  ValueType Type;
+  bool Mutable;
+  wasm::WasmInitExpr InitExpr;
+};
+
+struct LocalDecl {
+  ValueType Type;
+  uint32_t Count;
+};
+
+struct Function {
+  std::vector<LocalDecl> Locals;
+  yaml::BinaryRef Body;
+};
+
+struct Relocation {
+  RelocType Type;
+  uint32_t Index;
+  yaml::Hex32 Offset;
+  yaml::Hex32 Addend;
+};
+
+struct DataSegment {
+  uint32_t Index;
+  wasm::WasmInitExpr Offset;
+  yaml::BinaryRef Content;
+};
+
+struct Signature {
+  Signature() : Form(wasm::WASM_TYPE_FUNC) {}
+
+  uint32_t Index;
+  SignatureForm Form;
+  std::vector<ValueType> ParamTypes;
+  ValueType ReturnType;
+};
+
+struct Section {
+  Section(SectionType SecType) : Type(SecType) {}
+
+  SectionType Type;
+  std::vector<Relocation> Relocations;
+};
+
+struct CustomSection : Section {
+  CustomSection() : Section(wasm::WASM_SEC_CUSTOM) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_CUSTOM;
+  }
+
+  StringRef Name;
+  yaml::BinaryRef Payload;
+};
+
+struct TypeSection : Section {
+  TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_TYPE;
+  }
+
+  std::vector<Signature> Signatures;
+};
+
+struct ImportSection : Section {
+  ImportSection() : Section(wasm::WASM_SEC_IMPORT) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_IMPORT;
+  }
+
+  std::vector<Import> Imports;
+};
+
+struct FunctionSection : Section {
+  FunctionSection() : Section(wasm::WASM_SEC_FUNCTION) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_FUNCTION;
+  }
+
+  std::vector<uint32_t> FunctionTypes;
+};
+
+struct TableSection : Section {
+  TableSection() : Section(wasm::WASM_SEC_TABLE) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_TABLE;
+  }
+
+  std::vector<Table> Tables;
+};
+
+struct MemorySection : Section {
+  MemorySection() : Section(wasm::WASM_SEC_MEMORY) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_MEMORY;
+  }
+
+  std::vector<Limits> Memories;
+};
+
+struct GlobalSection : Section {
+  GlobalSection() : Section(wasm::WASM_SEC_GLOBAL) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_GLOBAL;
+  }
+
+  std::vector<Global> Globals;
+};
+
+struct ExportSection : Section {
+  ExportSection() : Section(wasm::WASM_SEC_EXPORT) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_EXPORT;
+  }
+
+  std::vector<Export> Exports;
+};
+
+struct StartSection : Section {
+  StartSection() : Section(wasm::WASM_SEC_START) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_START;
+  }
+
+  uint32_t StartFunction;
+};
+
+struct ElemSection : Section {
+  ElemSection() : Section(wasm::WASM_SEC_ELEM) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_ELEM;
+  }
+
+  std::vector<ElemSegment> Segments;
+};
+
+struct CodeSection : Section {
+  CodeSection() : Section(wasm::WASM_SEC_CODE) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_CODE;
+  }
+
+  std::vector<Function> Functions;
+};
+
+struct DataSection : Section {
+  DataSection() : Section(wasm::WASM_SEC_DATA) {}
+  static bool classof(const Section *S) {
+    return S->Type == wasm::WASM_SEC_DATA;
+  }
+
+  std::vector<DataSegment> Segments;
+};
+
+struct Object {
+  FileHeader Header;
+  std::vector<std::unique_ptr<Section>> Sections;
+};
+
+} // end namespace WasmYAML
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::WasmYAML::Section>)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Signature)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ValueType)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Table)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Import)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Export)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ElemSegment)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Limits)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DataSegment)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Global)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
+LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<WasmYAML::FileHeader> {
+  static void mapping(IO &IO, WasmYAML::FileHeader &FileHdr);
+};
+
+template <> struct MappingTraits<std::unique_ptr<WasmYAML::Section>> {
+  static void mapping(IO &IO, std::unique_ptr<WasmYAML::Section> &Section);
+};
+
+template <> struct MappingTraits<WasmYAML::Object> {
+  static void mapping(IO &IO, WasmYAML::Object &Object);
+};
+
+template <> struct MappingTraits<WasmYAML::Import> {
+  static void mapping(IO &IO, WasmYAML::Import &Import);
+};
+
+template <> struct MappingTraits<WasmYAML::Export> {
+  static void mapping(IO &IO, WasmYAML::Export &Export);
+};
+
+template <> struct MappingTraits<WasmYAML::Global> {
+  static void mapping(IO &IO, WasmYAML::Global &Global);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::SectionType> {
+  static void enumeration(IO &IO, WasmYAML::SectionType &Type);
+};
+
+template <> struct MappingTraits<WasmYAML::Signature> {
+  static void mapping(IO &IO, WasmYAML::Signature &Signature);
+};
+
+template <> struct MappingTraits<WasmYAML::Table> {
+  static void mapping(IO &IO, WasmYAML::Table &Table);
+};
+
+template <> struct MappingTraits<WasmYAML::Limits> {
+  static void mapping(IO &IO, WasmYAML::Limits &Limits);
+};
+
+template <> struct MappingTraits<WasmYAML::Function> {
+  static void mapping(IO &IO, WasmYAML::Function &Function);
+};
+
+template <> struct MappingTraits<WasmYAML::Relocation> {
+  static void mapping(IO &IO, WasmYAML::Relocation &Relocation);
+};
+
+template <> struct MappingTraits<WasmYAML::LocalDecl> {
+  static void mapping(IO &IO, WasmYAML::LocalDecl &LocalDecl);
+};
+
+template <> struct MappingTraits<wasm::WasmInitExpr> {
+  static void mapping(IO &IO, wasm::WasmInitExpr &Expr);
+};
+
+template <> struct MappingTraits<WasmYAML::DataSegment> {
+  static void mapping(IO &IO, WasmYAML::DataSegment &Segment);
+};
+
+template <> struct MappingTraits<WasmYAML::ElemSegment> {
+  static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
+  static void enumeration(IO &IO, WasmYAML::ValueType &Type);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::ExportKind> {
+  static void enumeration(IO &IO, WasmYAML::ExportKind &Kind);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::TableType> {
+  static void enumeration(IO &IO, WasmYAML::TableType &Type);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::Opcode> {
+  static void enumeration(IO &IO, WasmYAML::Opcode &Opcode);
+};
+
+template <> struct ScalarEnumerationTraits<WasmYAML::RelocType> {
+  static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif

Modified: llvm/trunk/include/llvm/Support/Wasm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Wasm.h?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Wasm.h (original)
+++ llvm/trunk/include/llvm/Support/Wasm.h Thu Mar 30 14:44:09 2017
@@ -30,11 +30,83 @@ struct WasmObjectHeader {
   uint32_t Version;
 };
 
-struct WasmSection {
-  uint32_t Type;             // Section type (See below)
-  uint32_t Offset;           // Offset with in the file
-  StringRef Name;            // Section name (User-defined sections only)
-  ArrayRef<uint8_t> Content; // Section content
+struct WasmSignature {
+  std::vector<int32_t> ParamTypes;
+  int32_t ReturnType;
+};
+
+struct WasmImport {
+  StringRef Module;
+  StringRef Field;
+  uint32_t Kind;
+  union {
+    uint32_t SigIndex;
+    int32_t GlobalType;
+  };
+  bool GlobalMutable;
+};
+
+struct WasmExport {
+  StringRef Name;
+  uint32_t Kind;
+  uint32_t Index;
+};
+
+struct WasmLimits {
+  uint32_t Flags;
+  uint32_t Initial;
+  uint32_t Maximum;
+};
+
+struct WasmTable {
+  int32_t ElemType;
+  WasmLimits Limits;
+};
+
+struct WasmInitExpr {
+  uint8_t Opcode;
+  union {
+    int32_t Int32;
+    int64_t Int64;
+    int32_t Float32;
+    int64_t Float64;
+    uint32_t Global;
+  } Value;
+};
+
+struct WasmGlobal {
+  int32_t Type;
+  bool Mutable;
+  WasmInitExpr InitExpr;
+};
+
+struct WasmLocalDecl {
+  int32_t Type;
+  uint32_t Count;
+};
+
+struct WasmFunction {
+  std::vector<WasmLocalDecl> Locals;
+  ArrayRef<uint8_t> Body;
+};
+
+struct WasmDataSegment {
+  uint32_t Index;
+  WasmInitExpr Offset;
+  ArrayRef<uint8_t> Content;
+};
+
+struct WasmElemSegment {
+  uint32_t TableIndex;
+  WasmInitExpr Offset;
+  std::vector<uint32_t> Functions;
+};
+
+struct WasmRelocation {
+  uint32_t Type;         // The type of the relocation.
+  int32_t Index;         // Index into function to global index space.
+  uint64_t Offset;       // Offset from the start of the section.
+  uint64_t Addend;       // A value to add to the symbol.
 };
 
 enum : unsigned {
@@ -86,6 +158,10 @@ enum : unsigned {
   WASM_NAMES_LOCAL       = 0x2,
 };
 
+enum : unsigned {
+  WASM_LIMITS_FLAG_HAS_MAX = 0x1,
+};
+
 // Subset of types that a value can have
 enum class ValType {
   I32 = WASM_TYPE_I32,
@@ -100,6 +176,8 @@ enum : unsigned {
 #include "WasmRelocs/WebAssembly.def"
 };
 
+#undef WASM_RELOC
+
 } // end namespace wasm
 } // end namespace llvm
 

Modified: llvm/trunk/lib/Object/WasmObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/WasmObjectFile.cpp?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/lib/Object/WasmObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/WasmObjectFile.cpp Thu Mar 30 14:44:09 2017
@@ -38,12 +38,33 @@ ObjectFile::createWasmObjectFile(MemoryB
   return std::move(ObjectFile);
 }
 
+#define VARINT7_MAX ((1<<7)-1)
+#define VARINT7_MIN (-(1<<7))
+#define VARUINT7_MAX (1<<7)
+#define VARUINT1_MAX (1)
+
+static uint8_t readUint8(const uint8_t *&Ptr) { return *Ptr++; }
+
 static uint32_t readUint32(const uint8_t *&Ptr) {
   uint32_t Result = support::endian::read32le(Ptr);
   Ptr += sizeof(Result);
   return Result;
 }
 
+static int32_t readFloat32(const uint8_t *&Ptr) {
+  int32_t Result = 0;
+  memcpy(&Result, Ptr, sizeof(Result));
+  Ptr += sizeof(Result);
+  return Result;
+}
+
+static int64_t readFloat64(const uint8_t *&Ptr) {
+  int64_t Result = 0;
+  memcpy(&Result, Ptr, sizeof(Result));
+  Ptr += sizeof(Result);
+  return Result;
+}
+
 static uint64_t readULEB128(const uint8_t *&Ptr) {
   unsigned Count;
   uint64_t Result = decodeULEB128(Ptr, &Count);
@@ -58,12 +79,98 @@ static StringRef readString(const uint8_
   return Return;
 }
 
-static Error readSection(wasm::WasmSection &Section, const uint8_t *&Ptr,
+static int64_t readLEB128(const uint8_t *&Ptr) {
+  unsigned Count;
+  uint64_t Result = decodeSLEB128(Ptr, &Count);
+  Ptr += Count;
+  return Result;
+}
+
+static uint8_t readVaruint1(const uint8_t *&Ptr) {
+  int64_t result = readLEB128(Ptr);
+  assert(result <= VARUINT1_MAX && result >= 0);
+  return result;
+}
+
+static int8_t readVarint7(const uint8_t *&Ptr) {
+  int64_t result = readLEB128(Ptr);
+  assert(result <= VARINT7_MAX && result >= VARINT7_MIN);
+  return result;
+}
+
+static uint8_t readVaruint7(const uint8_t *&Ptr) {
+  uint64_t result = readULEB128(Ptr);
+  assert(result <= VARUINT7_MAX && result >= 0);
+  return result;
+}
+
+static int32_t readVarint32(const uint8_t *&Ptr) {
+  int64_t result = readLEB128(Ptr);
+  assert(result <= INT32_MAX && result >= INT32_MIN);
+  return result;
+}
+
+static uint32_t readVaruint32(const uint8_t *&Ptr) {
+  uint64_t result = readULEB128(Ptr);
+  assert(result <= UINT32_MAX && result >= 0);
+  return result;
+}
+
+static int64_t readVarint64(const uint8_t *&Ptr) {
+  return readLEB128(Ptr);
+}
+
+static uint8_t readOpcode(const uint8_t *&Ptr) {
+  return readUint8(Ptr);
+}
+
+static Error readInitExpr(wasm::WasmInitExpr &Expr, const uint8_t *&Ptr) {
+  Expr.Opcode = readOpcode(Ptr);
+
+  switch (Expr.Opcode) {
+  case wasm::WASM_OPCODE_I32_CONST:
+    Expr.Value.Int32 = readVarint32(Ptr);
+    break;
+  case wasm::WASM_OPCODE_I64_CONST:
+    Expr.Value.Int64 = readVarint64(Ptr);
+    break;
+  case wasm::WASM_OPCODE_F32_CONST:
+    Expr.Value.Float32 = readFloat32(Ptr);
+    break;
+  case wasm::WASM_OPCODE_F64_CONST:
+    Expr.Value.Float64 = readFloat64(Ptr);
+    break;
+  case wasm::WASM_OPCODE_GET_GLOBAL:
+    Expr.Value.Global = readUint32(Ptr);
+    break;
+  default:
+    return make_error<GenericBinaryError>("Invalid opcode in init_expr",
+                                          object_error::parse_failed);
+  }
+
+  uint8_t EndOpcode = readOpcode(Ptr);
+  if (EndOpcode != wasm::WASM_OPCODE_END) {
+    return make_error<GenericBinaryError>("Invalid init_expr",
+                                          object_error::parse_failed);
+  }
+  return Error::success();
+}
+
+static wasm::WasmLimits readLimits(const uint8_t *&Ptr) {
+  wasm::WasmLimits Result;
+  Result.Flags = readVaruint1(Ptr);
+  Result.Initial = readVaruint32(Ptr);
+  if (Result.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
+    Result.Maximum = readVaruint32(Ptr);
+  return Result;
+}
+
+static Error readSection(WasmSection &Section, const uint8_t *&Ptr,
                          const uint8_t *Start) {
   // TODO(sbc): Avoid reading past EOF in the case of malformed files.
   Section.Offset = Ptr - Start;
-  Section.Type = readULEB128(Ptr);
-  uint32_t Size = readULEB128(Ptr);
+  Section.Type = readVaruint7(Ptr);
+  uint32_t Size = readVaruint32(Ptr);
   if (Size == 0)
     return make_error<StringError>("Zero length section",
                                    object_error::parse_failed);
@@ -73,7 +180,7 @@ static Error readSection(wasm::WasmSecti
 }
 
 WasmObjectFile::WasmObjectFile(MemoryBufferRef Buffer, Error &Err)
-    : ObjectFile(Binary::ID_Wasm, Buffer) {
+    : ObjectFile(Binary::ID_Wasm, Buffer), StartFunction(-1) {
   ErrorAsOutParameter ErrAsOutParam(&Err);
   Header.Magic = getData().substr(0, 4);
   if (Header.Magic != StringRef("\0asm", 4)) {
@@ -90,22 +197,391 @@ WasmObjectFile::WasmObjectFile(MemoryBuf
   }
 
   const uint8_t *Eof = getPtr(getData().size());
-  wasm::WasmSection Sec;
+  WasmSection Sec;
   while (Ptr < Eof) {
     if ((Err = readSection(Sec, Ptr, getPtr(0))))
       return;
-    if (Sec.Type == wasm::WASM_SEC_CUSTOM) {
-      if ((Err =
-               parseCustomSection(Sec, Sec.Content.data(), Sec.Content.size())))
-        return;
-    }
+    if ((Err = parseSection(Sec)))
+      return;
+
     Sections.push_back(Sec);
   }
 }
 
-Error WasmObjectFile::parseCustomSection(wasm::WasmSection &Sec,
-                                         const uint8_t *Ptr, size_t Length) {
+Error WasmObjectFile::parseSection(WasmSection &Sec) {
+  const uint8_t* Start = Sec.Content.data();
+  const uint8_t* End = Start + Sec.Content.size();
+  switch (Sec.Type) {
+  case wasm::WASM_SEC_CUSTOM:
+    return parseCustomSection(Sec, Start, End);
+  case wasm::WASM_SEC_TYPE:
+    return parseTypeSection(Start, End);
+  case wasm::WASM_SEC_IMPORT:
+    return parseImportSection(Start, End);
+  case wasm::WASM_SEC_FUNCTION:
+    return parseFunctionSection(Start, End);
+  case wasm::WASM_SEC_TABLE:
+    return parseTableSection(Start, End);
+  case wasm::WASM_SEC_MEMORY:
+    return parseMemorySection(Start, End);
+  case wasm::WASM_SEC_GLOBAL:
+    return parseGlobalSection(Start, End);
+  case wasm::WASM_SEC_EXPORT:
+    return parseExportSection(Start, End);
+  case wasm::WASM_SEC_START:
+    return parseStartSection(Start, End);
+  case wasm::WASM_SEC_ELEM:
+    return parseElemSection(Start, End);
+  case wasm::WASM_SEC_CODE:
+    return parseCodeSection(Start, End);
+  case wasm::WASM_SEC_DATA:
+    return parseDataSection(Start, End);
+  default:
+    return make_error<GenericBinaryError>("Bad section type",
+                                          object_error::parse_failed);
+  }
+}
+
+Error WasmObjectFile::parseNameSection(const uint8_t *Ptr, const uint8_t *End) {
+  while (Ptr < End) {
+    uint8_t Type = readVarint7(Ptr);
+    uint32_t Size = readVaruint32(Ptr);
+    switch (Type) {
+    case wasm::WASM_NAMES_FUNCTION: {
+      uint32_t Count = readVaruint32(Ptr);
+      while (Count--) {
+        /*uint32_t Index =*/readVaruint32(Ptr);
+        StringRef Name = readString(Ptr);
+        if (Name.size())
+          Symbols.emplace_back(Name,
+                               WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME);
+      }
+      break;
+    }
+    // Ignore local names for now
+    case wasm::WASM_NAMES_LOCAL:
+    default:
+      Ptr += Size;
+      break;
+    }
+  }
+
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Name 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)
+      return &Section;
+  }
+  return nullptr;
+}
+
+WasmSection* WasmObjectFile::findSectionByType(uint32_t Type) {
+  assert(Type != wasm::WASM_SEC_CUSTOM);
+  for (WasmSection& Section : Sections) {
+    if (Section.Type == Type)
+      return &Section;
+  }
+  return nullptr;
+}
+
+Error WasmObjectFile::parseRelocSection(StringRef Name, const uint8_t *Ptr,
+                                        const uint8_t *End) {
+  uint8_t SectionCode = readVarint7(Ptr);
+  WasmSection* Section = nullptr;
+  if (SectionCode == wasm::WASM_SEC_CUSTOM) {
+    StringRef Name = readString(Ptr);
+    Section = findCustomSectionByName(Name);
+  } else {
+    Section = findSectionByType(SectionCode);
+  }
+  if (!Section)
+    return make_error<GenericBinaryError>("Invalid section code",
+                                          object_error::parse_failed);
+  uint32_t RelocCount = readVaruint32(Ptr);
+  while (RelocCount--) {
+    wasm::WasmRelocation Reloc;
+    memset(&Reloc, 0, sizeof(Reloc));
+    Reloc.Type = readVaruint32(Ptr);
+    Reloc.Offset = readVaruint32(Ptr);
+    Reloc.Index = readVaruint32(Ptr);
+    switch (Reloc.Type) {
+    case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
+    case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
+    case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
+      break;
+    case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
+    case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+    case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+      Reloc.Addend = readVaruint32(Ptr);
+      break;
+    default:
+      return make_error<GenericBinaryError>("Bad relocation type",
+                                            object_error::parse_failed);
+    }
+    Section->Relocations.push_back(Reloc);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Reloc section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseCustomSection(WasmSection &Sec,
+                                         const uint8_t *Ptr, const uint8_t *End) {
   Sec.Name = readString(Ptr);
+  if (Sec.Name == "name") {
+    if (Error Err = parseNameSection(Ptr, End))
+      return Err;
+  } else if (Sec.Name.startswith("reloc.")) {
+    if (Error Err = parseRelocSection(Sec.Name, Ptr, End))
+      return Err;
+  }
+  return Error::success();
+}
+
+Error WasmObjectFile::parseTypeSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  Signatures.reserve(Count);
+  while (Count--) {
+    wasm::WasmSignature Sig;
+    Sig.ReturnType = wasm::WASM_TYPE_NORESULT;
+    int8_t Form = readVarint7(Ptr);
+    if (Form != wasm::WASM_TYPE_FUNC) {
+      return make_error<GenericBinaryError>("Invalid signature type",
+                                            object_error::parse_failed);
+    }
+    uint32_t ParamCount = readVaruint32(Ptr);
+    Sig.ParamTypes.reserve(ParamCount);
+    while (ParamCount--) {
+      uint32_t ParamType = readVarint7(Ptr);
+      Sig.ParamTypes.push_back(ParamType);
+    }
+    uint32_t ReturnCount = readVaruint32(Ptr);
+    if (ReturnCount) {
+      if (ReturnCount != 1) {
+        return make_error<GenericBinaryError>(
+            "Multiple return types not supported", object_error::parse_failed);
+      }
+      Sig.ReturnType = readVarint7(Ptr);
+    }
+    Signatures.push_back(Sig);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Type section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseImportSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  Imports.reserve(Count);
+  while (Count--) {
+    wasm::WasmImport Im;
+    Im.Module = readString(Ptr);
+    Im.Field = readString(Ptr);
+    Im.Kind = readUint8(Ptr);
+    switch (Im.Kind) {
+    case wasm::WASM_EXTERNAL_FUNCTION:
+      Im.SigIndex = readVaruint32(Ptr);
+      Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::FUNCTION_IMPORT);
+      break;
+    case wasm::WASM_EXTERNAL_GLOBAL:
+      Im.GlobalType = readVarint7(Ptr);
+      Im.GlobalMutable = readVaruint1(Ptr);
+      Symbols.emplace_back(Im.Field, WasmSymbol::SymbolType::GLOBAL_IMPORT);
+      break;
+    default:
+      // TODO(sbc): Handle other kinds of imports
+      return make_error<GenericBinaryError>(
+          "Unexpected import kind", object_error::parse_failed);
+    }
+    Imports.push_back(Im);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Import section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseFunctionSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  FunctionTypes.reserve(Count);
+  while (Count--) {
+    FunctionTypes.push_back(readVaruint32(Ptr));
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Function section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseTableSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  Tables.reserve(Count);
+  while (Count--) {
+    wasm::WasmTable Table;
+    Table.ElemType = readVarint7(Ptr);
+    if (Table.ElemType != wasm::WASM_TYPE_ANYFUNC) {
+      return make_error<GenericBinaryError>("Invalid table element type",
+                                            object_error::parse_failed);
+    }
+    Table.Limits = readLimits(Ptr);
+    Tables.push_back(Table);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Table section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseMemorySection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  Memories.reserve(Count);
+  while (Count--) {
+    Memories.push_back(readLimits(Ptr));
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Memory section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseGlobalSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  Globals.reserve(Count);
+  while (Count--) {
+    wasm::WasmGlobal Global;
+    Global.Type = readVarint7(Ptr);
+    Global.Mutable = readVaruint1(Ptr);
+    size_t offset = Ptr - getPtr(0);
+    if (Error Err = readInitExpr(Global.InitExpr, Ptr)) {
+      offset = Ptr - getPtr(0);
+      return Err;
+    }
+    Globals.push_back(Global);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Global section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseExportSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  Exports.reserve(Count);
+  while (Count--) {
+    wasm::WasmExport Ex;
+    Ex.Name = readString(Ptr);
+    Ex.Kind = readUint8(Ptr);
+    Ex.Index = readVaruint32(Ptr);
+    Exports.push_back(Ex);
+    switch (Ex.Kind) {
+    case wasm::WASM_EXTERNAL_FUNCTION:
+      Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::FUNCTION_EXPORT);
+      break;
+    case wasm::WASM_EXTERNAL_GLOBAL:
+      Symbols.emplace_back(Ex.Name, WasmSymbol::SymbolType::GLOBAL_EXPORT);
+      break;
+    default:
+      // TODO(sbc): Handle other kinds of exports
+      return make_error<GenericBinaryError>(
+          "Unexpected export kind", object_error::parse_failed);
+    }
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Export section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseStartSection(const uint8_t *Ptr, const uint8_t *End) {
+  StartFunction = readVaruint32(Ptr);
+  if (StartFunction < FunctionTypes.size())
+    return make_error<GenericBinaryError>("Invalid start function",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseCodeSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t FunctionCount = readVaruint32(Ptr);
+  if (FunctionCount != FunctionTypes.size()) {
+    return make_error<GenericBinaryError>("Invalid function count",
+                                          object_error::parse_failed);
+  }
+
+  CodeSection = ArrayRef<uint8_t>(Ptr, End - Ptr);
+
+  while (FunctionCount--) {
+    wasm::WasmFunction Function;
+    uint32_t FunctionSize = readVaruint32(Ptr);
+    const uint8_t *FunctionEnd = Ptr + FunctionSize;
+
+    uint32_t NumLocalDecls = readVaruint32(Ptr);
+    Function.Locals.reserve(NumLocalDecls);
+    while (NumLocalDecls--) {
+      wasm::WasmLocalDecl Decl;
+      Decl.Count = readVaruint32(Ptr);
+      Decl.Type = readVarint7(Ptr);
+      Function.Locals.push_back(Decl);
+    }
+
+    uint32_t BodySize = FunctionEnd - Ptr;
+    Function.Body = ArrayRef<uint8_t>(Ptr, BodySize);
+    Ptr += BodySize;
+    assert(Ptr == FunctionEnd);
+    Functions.push_back(Function);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Code section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseElemSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  ElemSegments.reserve(Count);
+  while (Count--) {
+    wasm::WasmElemSegment Segment;
+    Segment.TableIndex = readVaruint32(Ptr);
+    if (Segment.TableIndex != 0) {
+      return make_error<GenericBinaryError>("Invalid TableIndex",
+                                            object_error::parse_failed);
+    }
+    if (Error Err = readInitExpr(Segment.Offset, Ptr))
+      return Err;
+    uint32_t NumElems = readVaruint32(Ptr);
+    while (NumElems--) {
+      Segment.Functions.push_back(readVaruint32(Ptr));
+    }
+    ElemSegments.push_back(Segment);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Elem section ended prematurely",
+                                          object_error::parse_failed);
+  return Error::success();
+}
+
+Error WasmObjectFile::parseDataSection(const uint8_t *Ptr, const uint8_t *End) {
+  uint32_t Count = readVaruint32(Ptr);
+  DataSegments.reserve(Count);
+  while (Count--) {
+    wasm::WasmDataSegment Segment;
+    Segment.Index = readVaruint32(Ptr);
+    if (Error Err = readInitExpr(Segment.Offset, Ptr))
+      return Err;
+    uint32_t Size = readVaruint32(Ptr);
+    Segment.Content = ArrayRef<uint8_t>(Ptr, Size);
+    Ptr += Size;
+    DataSegments.push_back(Segment);
+  }
+  if (Ptr != End)
+    return make_error<GenericBinaryError>("Data section ended prematurely",
+                                          object_error::parse_failed);
   return Error::success();
 }
 
@@ -117,37 +593,47 @@ const wasm::WasmObjectHeader &WasmObject
   return Header;
 }
 
-void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
-  llvm_unreachable("not yet implemented");
-}
-
-std::error_code WasmObjectFile::printSymbolName(raw_ostream &OS,
-                                                DataRefImpl Symb) const {
-  llvm_unreachable("not yet implemented");
-  return object_error::invalid_symbol_index;
-}
+void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.a++; }
 
 uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const {
-  llvm_unreachable("not yet implemented");
-  return 0;
+  const WasmSymbol &Sym = getWasmSymbol(Symb);
+  switch (Sym.Type) {
+  case WasmSymbol::SymbolType::FUNCTION_IMPORT:
+    return object::SymbolRef::SF_Undefined | SymbolRef::SF_Executable;
+  case WasmSymbol::SymbolType::FUNCTION_EXPORT:
+    return object::SymbolRef::SF_Global | SymbolRef::SF_Executable;
+  case WasmSymbol::SymbolType::DEBUG_FUNCTION_NAME:
+    return object::SymbolRef::SF_Executable;
+  case WasmSymbol::SymbolType::GLOBAL_IMPORT:
+    return object::SymbolRef::SF_Undefined;
+  case WasmSymbol::SymbolType::GLOBAL_EXPORT:
+    return object::SymbolRef::SF_Global;
+  }
 }
 
 basic_symbol_iterator WasmObjectFile::symbol_begin() const {
-  return BasicSymbolRef(DataRefImpl(), this);
+  DataRefImpl Ref;
+  Ref.d.a = 0;
+  return BasicSymbolRef(Ref, this);
 }
 
 basic_symbol_iterator WasmObjectFile::symbol_end() const {
-  return BasicSymbolRef(DataRefImpl(), this);
+  DataRefImpl Ref;
+  Ref.d.a = Symbols.size();
+  return BasicSymbolRef(Ref, this);
+}
+
+const WasmSymbol &WasmObjectFile::getWasmSymbol(DataRefImpl Symb) const {
+  return Symbols[Symb.d.a];
 }
 
 Expected<StringRef> WasmObjectFile::getSymbolName(DataRefImpl Symb) const {
-  llvm_unreachable("not yet implemented");
-  return errorCodeToError(object_error::invalid_symbol_index);
+  const WasmSymbol &Sym = getWasmSymbol(Symb);
+  return Sym.Name;
 }
 
 Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
-  llvm_unreachable("not yet implemented");
-  return errorCodeToError(object_error::invalid_symbol_index);
+  return (uint64_t)Symb.d.a;
 }
 
 uint64_t WasmObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
@@ -181,7 +667,7 @@ void WasmObjectFile::moveSectionNext(Dat
 
 std::error_code WasmObjectFile::getSectionName(DataRefImpl Sec,
                                                StringRef &Res) const {
-  const wasm::WasmSection &S = Sections[Sec.d.a];
+  const WasmSection &S = Sections[Sec.d.a];
 #define ECase(X)                                                               \
   case wasm::WASM_SEC_##X:                                                     \
     Res = #X;                                                                  \
@@ -211,13 +697,13 @@ std::error_code WasmObjectFile::getSecti
 uint64_t WasmObjectFile::getSectionAddress(DataRefImpl Sec) const { return 0; }
 
 uint64_t WasmObjectFile::getSectionSize(DataRefImpl Sec) const {
-  const wasm::WasmSection &S = Sections[Sec.d.a];
+  const WasmSection &S = Sections[Sec.d.a];
   return S.Content.size();
 }
 
 std::error_code WasmObjectFile::getSectionContents(DataRefImpl Sec,
                                                    StringRef &Res) const {
-  const wasm::WasmSection &S = Sections[Sec.d.a];
+  const WasmSection &S = Sections[Sec.d.a];
   // This will never fail since wasm sections can never be empty (user-sections
   // must have a name and non-user sections each have a defined structure).
   Res = StringRef(reinterpret_cast<const char *>(S.Content.data()),
@@ -234,13 +720,11 @@ bool WasmObjectFile::isSectionCompressed
 }
 
 bool WasmObjectFile::isSectionText(DataRefImpl Sec) const {
-  const wasm::WasmSection &S = Sections[Sec.d.a];
-  return S.Type == wasm::WASM_SEC_CODE;
+  return getWasmSection(Sec).Type == wasm::WASM_SEC_CODE;
 }
 
 bool WasmObjectFile::isSectionData(DataRefImpl Sec) const {
-  const wasm::WasmSection &S = Sections[Sec.d.a];
-  return S.Type == wasm::WASM_SEC_DATA;
+  return getWasmSection(Sec).Type == wasm::WASM_SEC_DATA;
 }
 
 bool WasmObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
@@ -249,31 +733,28 @@ bool WasmObjectFile::isSectionVirtual(Da
 
 bool WasmObjectFile::isSectionBitcode(DataRefImpl Sec) const { return false; }
 
-relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Sec) const {
-  llvm_unreachable("not yet implemented");
-  RelocationRef Rel;
-  return relocation_iterator(Rel);
-}
-
-relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Sec) const {
-  llvm_unreachable("not yet implemented");
-  RelocationRef Rel;
-  return relocation_iterator(Rel);
+relocation_iterator WasmObjectFile::section_rel_begin(DataRefImpl Ref) const {
+  DataRefImpl RelocRef;
+  RelocRef.d.a = Ref.d.a;
+  RelocRef.d.b = 0;
+  return relocation_iterator(RelocationRef(RelocRef, this));
 }
 
-section_iterator WasmObjectFile::getRelocatedSection(DataRefImpl Sec) const {
-  llvm_unreachable("not yet implemented");
-  SectionRef Ref;
-  return section_iterator(Ref);
+relocation_iterator WasmObjectFile::section_rel_end(DataRefImpl Ref) const {
+  const WasmSection &Sec = getWasmSection(Ref);
+  DataRefImpl RelocRef;
+  RelocRef.d.a = Ref.d.a;
+  RelocRef.d.b = Sec.Relocations.size();
+  return relocation_iterator(RelocationRef(RelocRef, this));
 }
 
 void WasmObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
-  llvm_unreachable("not yet implemented");
+  Rel.d.b++;
 }
 
-uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Rel) const {
-  llvm_unreachable("not yet implemented");
-  return 0;
+uint64_t WasmObjectFile::getRelocationOffset(DataRefImpl Ref) const {
+  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
+  return Rel.Offset;
 }
 
 symbol_iterator WasmObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
@@ -282,14 +763,28 @@ symbol_iterator WasmObjectFile::getReloc
   return symbol_iterator(Ref);
 }
 
-uint64_t WasmObjectFile::getRelocationType(DataRefImpl Rel) const {
-  llvm_unreachable("not yet implemented");
-  return 0;
+uint64_t WasmObjectFile::getRelocationType(DataRefImpl Ref) const {
+  const wasm::WasmRelocation &Rel = getWasmRelocation(Ref);
+  return Rel.Type;
 }
 
 void WasmObjectFile::getRelocationTypeName(
-    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
-  llvm_unreachable("not yet implemented");
+    DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
+  const wasm::WasmRelocation& Rel = getWasmRelocation(Ref);
+  StringRef Res = "Unknown";
+
+#define WASM_RELOC(name, value)  \
+  case wasm::name:              \
+    Res = #name;               \
+    break;
+
+  switch (Rel.Type) {
+#include "llvm/Support/WasmRelocs/WebAssembly.def"
+  }
+
+#undef WASM_RELOC
+
+  Result.append(Res.begin(), Res.end());
 }
 
 section_iterator WasmObjectFile::section_begin() const {
@@ -316,7 +811,25 @@ SubtargetFeatures WasmObjectFile::getFea
 
 bool WasmObjectFile::isRelocatableObject() const { return false; }
 
-const wasm::WasmSection *
+const WasmSection &WasmObjectFile::getWasmSection(DataRefImpl Ref) const {
+  assert(Ref.d.a >= 0 && Ref.d.a < Sections.size());
+  return Sections[Ref.d.a];
+}
+
+const WasmSection &
 WasmObjectFile::getWasmSection(const SectionRef &Section) const {
-  return &Sections[Section.getRawDataRefImpl().d.a];
+  return getWasmSection(Section.getRawDataRefImpl());
+}
+
+const wasm::WasmRelocation &
+WasmObjectFile::getWasmRelocation(const RelocationRef &Ref) const {
+  return getWasmRelocation(Ref.getRawDataRefImpl());
+}
+
+const wasm::WasmRelocation &
+WasmObjectFile::getWasmRelocation(DataRefImpl Ref) const {
+  assert(Ref.d.a >= 0 && Ref.d.a < Sections.size());
+  const WasmSection& Sec = Sections[Ref.d.a];
+  assert(Ref.d.b >= 0 && Ref.d.b < Sec.Relocations.size());
+  return Sec.Relocations[Ref.d.b];
 }

Modified: llvm/trunk/lib/ObjectYAML/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/CMakeLists.txt?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/CMakeLists.txt (original)
+++ llvm/trunk/lib/ObjectYAML/CMakeLists.txt Thu Mar 30 14:44:09 2017
@@ -6,5 +6,6 @@ add_llvm_library(LLVMObjectYAML
   ELFYAML.cpp
   MachOYAML.cpp
   ObjectYAML.cpp
+  WasmYAML.cpp
   YAML.cpp
   )

Modified: llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ObjectYAML.cpp Thu Mar 30 14:44:09 2017
@@ -43,6 +43,9 @@ void MappingTraits<YamlObjectFile>::mapp
       ObjectFile.FatMachO.reset(new MachOYAML::UniversalBinary());
       MappingTraits<MachOYAML::UniversalBinary>::mapping(IO,
                                                          *ObjectFile.FatMachO);
+    } else if (IO.mapTag("!WASM")) {
+      ObjectFile.Wasm.reset(new WasmYAML::Object());
+      MappingTraits<WasmYAML::Object>::mapping(IO, *ObjectFile.Wasm);
     } else {
       Input &In = (Input &)IO;
       std::string Tag = In.getCurrentNode()->getRawTag();

Added: llvm/trunk/lib/ObjectYAML/WasmYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/WasmYAML.cpp?rev=299101&view=auto
==============================================================================
--- llvm/trunk/lib/ObjectYAML/WasmYAML.cpp (added)
+++ llvm/trunk/lib/ObjectYAML/WasmYAML.cpp Thu Mar 30 14:44:09 2017
@@ -0,0 +1,348 @@
+//===- WasmYAML.cpp - Wasm YAMLIO implementation --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines classes for handling the YAML representation of wasm.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ObjectYAML/WasmYAML.h"
+#include "llvm/Object/Wasm.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/MipsABIFlags.h"
+
+namespace llvm {
+namespace yaml {
+
+void MappingTraits<WasmYAML::FileHeader>::mapping(
+    IO &IO, WasmYAML::FileHeader &FileHdr) {
+  IO.mapRequired("Version", FileHdr.Version);
+}
+
+void MappingTraits<WasmYAML::Object>::mapping(IO &IO,
+                                              WasmYAML::Object &Object) {
+  IO.setContext(&Object);
+  IO.mapTag("!WASM", true);
+  IO.mapRequired("FileHeader", Object.Header);
+  IO.mapOptional("Sections", Object.Sections);
+  IO.setContext(nullptr);
+}
+
+static void commonSectionMapping(IO &IO, WasmYAML::Section &Section) {
+  IO.mapRequired("Type", Section.Type);
+  IO.mapOptional("Relocations", Section.Relocations);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapRequired("Name", Section.Name);
+  IO.mapRequired("Payload", Section.Payload);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::TypeSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("Signatures", Section.Signatures);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::ImportSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("Imports", Section.Imports);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::FunctionSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("FunctionTypes", Section.FunctionTypes);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::TableSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("Tables", Section.Tables);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::MemorySection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("Memories", Section.Memories);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::GlobalSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("Globals", Section.Globals);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::ExportSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("Exports", Section.Exports);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::StartSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("StartFunction", Section.StartFunction);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::ElemSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapOptional("Segments", Section.Segments);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::CodeSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapRequired("Functions", Section.Functions);
+}
+
+static void sectionMapping(IO &IO, WasmYAML::DataSection &Section) {
+  commonSectionMapping(IO, Section);
+  IO.mapRequired("Segments", Section.Segments);
+}
+
+void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping(
+    IO &IO, std::unique_ptr<WasmYAML::Section> &Section) {
+  WasmYAML::SectionType SectionType;
+  if (IO.outputting())
+    SectionType = Section->Type;
+  else
+    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()));
+    break;
+  case wasm::WASM_SEC_TYPE:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::TypeSection());
+    sectionMapping(IO, *cast<WasmYAML::TypeSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_IMPORT:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::ImportSection());
+    sectionMapping(IO, *cast<WasmYAML::ImportSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_FUNCTION:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::FunctionSection());
+    sectionMapping(IO, *cast<WasmYAML::FunctionSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_TABLE:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::TableSection());
+    sectionMapping(IO, *cast<WasmYAML::TableSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_MEMORY:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::MemorySection());
+    sectionMapping(IO, *cast<WasmYAML::MemorySection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_GLOBAL:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::GlobalSection());
+    sectionMapping(IO, *cast<WasmYAML::GlobalSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_EXPORT:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::ExportSection());
+    sectionMapping(IO, *cast<WasmYAML::ExportSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_START:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::StartSection());
+    sectionMapping(IO, *cast<WasmYAML::StartSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_ELEM:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::ElemSection());
+    sectionMapping(IO, *cast<WasmYAML::ElemSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_CODE:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::CodeSection());
+    sectionMapping(IO, *cast<WasmYAML::CodeSection>(Section.get()));
+    break;
+  case wasm::WASM_SEC_DATA:
+    if (!IO.outputting())
+      Section.reset(new WasmYAML::DataSection());
+    sectionMapping(IO, *cast<WasmYAML::DataSection>(Section.get()));
+    break;
+  default:
+    llvm_unreachable("Unknown section type");
+  }
+}
+
+void ScalarEnumerationTraits<WasmYAML::SectionType>::enumeration(
+    IO &IO, WasmYAML::SectionType &Type) {
+#define ECase(X) IO.enumCase(Type, #X, wasm::WASM_SEC_##X);
+  ECase(CUSTOM);
+  ECase(TYPE);
+  ECase(IMPORT);
+  ECase(FUNCTION);
+  ECase(TABLE);
+  ECase(MEMORY);
+  ECase(GLOBAL);
+  ECase(EXPORT);
+  ECase(START);
+  ECase(ELEM);
+  ECase(CODE);
+  ECase(DATA);
+#undef ECase
+}
+
+void MappingTraits<WasmYAML::Signature>::mapping(
+    IO &IO, WasmYAML::Signature &Signature) {
+  IO.mapOptional("Index", Signature.Index);
+  IO.mapRequired("ReturnType", Signature.ReturnType);
+  IO.mapRequired("ParamTypes", Signature.ParamTypes);
+}
+
+void MappingTraits<WasmYAML::Table>::mapping(IO &IO, WasmYAML::Table &Table) {
+  IO.mapRequired("ElemType", Table.ElemType);
+  IO.mapRequired("Limits", Table.TableLimits);
+}
+
+void MappingTraits<WasmYAML::Function>::mapping(IO &IO,
+                                                WasmYAML::Function &Function) {
+  IO.mapRequired("Locals", Function.Locals);
+  IO.mapRequired("Body", Function.Body);
+}
+
+void MappingTraits<WasmYAML::Relocation>::mapping(
+    IO &IO, WasmYAML::Relocation &Relocation) {
+  IO.mapRequired("Type", Relocation.Type);
+  IO.mapRequired("Index", Relocation.Index);
+  IO.mapRequired("Offset", Relocation.Offset);
+  IO.mapRequired("Addend", Relocation.Addend);
+}
+
+void MappingTraits<WasmYAML::LocalDecl>::mapping(
+    IO &IO, WasmYAML::LocalDecl &LocalDecl) {
+  IO.mapRequired("Type", LocalDecl.Type);
+  IO.mapRequired("Count", LocalDecl.Count);
+}
+
+void MappingTraits<WasmYAML::Limits>::mapping(IO &IO,
+                                              WasmYAML::Limits &Limits) {
+  if (!IO.outputting() || Limits.Flags)
+    IO.mapOptional("Flags", Limits.Flags);
+  IO.mapRequired("Initial", Limits.Initial);
+  if (!IO.outputting() || Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
+    IO.mapOptional("Maximum", Limits.Maximum);
+}
+
+void MappingTraits<WasmYAML::ElemSegment>::mapping(
+    IO &IO, WasmYAML::ElemSegment &Segment) {
+  IO.mapRequired("Offset", Segment.Offset);
+  IO.mapRequired("Functions", Segment.Functions);
+}
+
+void MappingTraits<WasmYAML::Import>::mapping(IO &IO,
+                                              WasmYAML::Import &Import) {
+  IO.mapRequired("Module", Import.Module);
+  IO.mapRequired("Field", Import.Field);
+  IO.mapRequired("Kind", Import.Kind);
+  if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
+    IO.mapRequired("SigIndex", Import.SigIndex);
+  } else if (Import.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
+    IO.mapRequired("GlobalType", Import.GlobalType);
+    IO.mapRequired("GlobalMutable", Import.GlobalMutable);
+  } else {
+    llvm_unreachable("unhandled import type");
+  }
+}
+
+void MappingTraits<WasmYAML::Export>::mapping(IO &IO,
+                                              WasmYAML::Export &Export) {
+  IO.mapRequired("Name", Export.Name);
+  IO.mapRequired("Kind", Export.Kind);
+  IO.mapRequired("Index", Export.Index);
+}
+
+void MappingTraits<WasmYAML::Global>::mapping(IO &IO,
+                                              WasmYAML::Global &Global) {
+  IO.mapRequired("Type", Global.Type);
+  IO.mapRequired("Mutable", Global.Mutable);
+  IO.mapRequired("InitExpr", Global.InitExpr);
+}
+
+void MappingTraits<wasm::WasmInitExpr>::mapping(IO &IO,
+                                                wasm::WasmInitExpr &Expr) {
+  WasmYAML::Opcode Op = Expr.Opcode;
+  IO.mapRequired("Opcode", Op);
+  Expr.Opcode = Op;
+  switch (Expr.Opcode) {
+  case wasm::WASM_OPCODE_I32_CONST:
+    IO.mapRequired("Value", Expr.Value.Int32);
+    break;
+  case wasm::WASM_OPCODE_I64_CONST:
+    IO.mapRequired("Value", Expr.Value.Int64);
+    break;
+  case wasm::WASM_OPCODE_F32_CONST:
+    IO.mapRequired("Value", Expr.Value.Float32);
+    break;
+  case wasm::WASM_OPCODE_F64_CONST:
+    IO.mapRequired("Value", Expr.Value.Float64);
+    break;
+  }
+}
+
+void MappingTraits<WasmYAML::DataSegment>::mapping(
+    IO &IO, WasmYAML::DataSegment &Segment) {
+  IO.mapRequired("Index", Segment.Index);
+  IO.mapRequired("Offset", Segment.Offset);
+  IO.mapRequired("Content", Segment.Content);
+}
+
+void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
+    IO &IO, WasmYAML::ValueType &Type) {
+#define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
+  ECase(I32);
+  ECase(I64);
+  ECase(F32);
+  ECase(F64);
+  ECase(ANYFUNC);
+  ECase(FUNC);
+  ECase(NORESULT);
+#undef ECase
+}
+
+void ScalarEnumerationTraits<WasmYAML::ExportKind>::enumeration(
+    IO &IO, WasmYAML::ExportKind &Kind) {
+#define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_EXTERNAL_##X);
+  ECase(FUNCTION);
+  ECase(TABLE);
+  ECase(MEMORY);
+  ECase(GLOBAL);
+#undef ECase
+}
+
+void ScalarEnumerationTraits<WasmYAML::Opcode>::enumeration(
+    IO &IO, WasmYAML::Opcode &Code) {
+#define ECase(X) IO.enumCase(Code, #X, wasm::WASM_OPCODE_##X);
+  ECase(END);
+  ECase(I32_CONST);
+  ECase(I64_CONST);
+  ECase(F64_CONST);
+  ECase(F32_CONST);
+  ECase(GET_GLOBAL);
+#undef ECase
+}
+
+void ScalarEnumerationTraits<WasmYAML::TableType>::enumeration(
+    IO &IO, WasmYAML::TableType &Type) {
+#define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
+  ECase(ANYFUNC);
+#undef ECase
+}
+
+void ScalarEnumerationTraits<WasmYAML::RelocType>::enumeration(
+    IO &IO, WasmYAML::RelocType &Type) {
+#define WASM_RELOC(name, value) IO.enumCase(Type, #name, wasm::name);
+#include "llvm/Support/WasmRelocs/WebAssembly.def"
+#undef WASM_RELOC
+}
+
+} // end namespace yaml
+} // end namespace llvm

Added: llvm/trunk/test/ObjectYAML/wasm/code_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/code_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/code_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/code_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,72 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - ReturnType:      F32
+        ParamTypes:
+          - I32
+      - ReturnType:      NORESULT
+        ParamTypes:
+          - I32
+          - I64
+  - Type:            FUNCTION
+    FunctionTypes:
+      - 0
+      - 1
+  - Type:            CODE
+    Relocations:
+      - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
+        Index:           0
+        Offset:          0x00000006
+        Addend:          0x00000000
+      - Type:            R_WEBASSEMBLY_FUNCTION_INDEX_LEB
+        Index:           1
+        Offset:          0x00000025
+        Addend:          0x00000000
+    Functions:
+      - Locals:
+         - Type:            I32
+           Count:           3
+        Body:            418080808000210020002101200111808080800000210220020F0B
+      - Locals:
+         - Type:            I32
+           Count:           1
+        Body:            108180808000210020000F0B
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:  - Type:            TYPE
+# CHECK:    Signatures:
+# CHECK:      - Index:           0
+# CHECK:        ReturnType:      F32
+# CHECK:        ParamTypes:
+# CHECK:          - I32
+# CHECK:      - Index:           1
+# CHECK:        ReturnType:      NORESULT
+# CHECK:        ParamTypes:
+# CHECK:          - I32
+# CHECK:          - I64
+# CHECK:  - Type:            CODE
+# CHECK:    Relocations:
+# CHECK:      - Type:            R_WEBASSEMBLY_TABLE_INDEX_SLEB
+# CHECK:        Index:           0
+# CHECK:        Offset:          0x00000006
+# CHECK:        Addend:          0x00000000
+# CHECK:      - Type:            R_WEBASSEMBLY_FUNCTION_INDEX_LEB
+# CHECK:        Index:           1
+# CHECK:        Offset:          0x00000025
+# CHECK:        Addend:          0x00000000
+# CHECK:    Functions:
+# CHECK:      - Locals:
+# CHECK:         - Type:            I32
+# CHECK:           Count:           3
+# CHECK:        Body:            418080808000210020002101200111808080800000210220020F0B
+# CHECK:      - Locals:
+# CHECK:         - Type:            I32
+# CHECK:           Count:           1
+# CHECK:        Body:            108180808000210020000F0B

Added: llvm/trunk/test/ObjectYAML/wasm/custom_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/custom_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/custom_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/custom_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,17 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            CUSTOM
+    Name:            foo
+    Payload:         03666F6F0401020304
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:  - Type:            CUSTOM
+# CHECK:    Name:            foo
+# CHECK:    Payload:         03666F6F0401020304
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/data_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/data_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/data_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/data_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,28 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            MEMORY
+    Memories:
+      - Initial:         0x00000003
+  - Type:            DATA
+    Segments:
+      - Index:           0
+        Offset:
+          Opcode:          I32_CONST
+          Value:           4
+        Content:         '10001000'
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:   - Type:            DATA
+# CHECK:     Segments:
+# CHECK:       - Index:           0
+# CHECK:         Offset:
+# CHECK:           Opcode:          I32_CONST
+# CHECK:           Value:           4
+# CHECK:         Content:         '10001000'
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/elem_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/elem_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/elem_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/elem_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,42 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            TABLE
+    Tables:         
+      - ElemType:          ANYFUNC
+        Limits:
+          Flags:           0x00000001
+          Initial:         0x00000010
+          Maximum:         0x00000011
+  - Type:            ELEM
+    Segments:
+      - Offset:
+          Opcode:        I32_CONST
+          Value:         3
+        Functions:
+          - 1
+      - Offset:
+          Opcode:        I32_CONST
+          Value:         5
+        Functions:
+          - 4
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:   - Type:            ELEM
+# CHECK:     Segments:
+# CHECK:       - Offset:
+# CHECK:           Opcode:           I32_CONST
+# CHECK:           Value:            3
+# CHECK:         Functions:
+# CHECK:           - 1
+# CHECK:       - Offset:
+# CHECK:           Opcode:           I32_CONST
+# CHECK:           Value:            5
+# CHECK:         Functions:
+# CHECK:           - 4
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/export_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/export_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/export_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/export_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,27 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            EXPORT
+    Exports:         
+      - Name:            foo
+        Kind:            FUNCTION
+        Index:           0
+      - Name:            bar
+        Kind:            FUNCTION
+        Index:           1
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:   - Type:            EXPORT
+# CHECK:     Exports:         
+# CHECK:       - Name:            foo
+# CHECK:         Kind:            FUNCTION
+# CHECK:         Index:           0
+# CHECK:       - Name:            bar
+# CHECK:         Kind:            FUNCTION
+# CHECK:         Index:           1
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/function_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/function_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/function_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/function_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,19 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            FUNCTION
+    FunctionTypes:   
+      - 1
+      - 0
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:   - Type:            FUNCTION
+# CHECK:     FunctionTypes:   
+# CHECK:       - 1
+# CHECK:       - 0
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/global_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/global_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/global_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/global_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,25 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            GLOBAL
+    Globals:         
+      - Type:        I32
+        Mutable:     false
+        InitExpr:
+          Opcode:          I64_CONST
+          Value:           -5
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:  - Type:            GLOBAL
+# CHECK:    Globals:         
+# CHECK:      - Type:        I32
+# CHECK:        Mutable:     false
+# CHECK:        InitExpr:
+# CHECK:          Opcode:          I64_CONST
+# CHECK:          Value:           -5
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/header.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/header.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/header.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/header.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,9 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/header_invalid_version.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/header_invalid_version.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/header_invalid_version.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/header_invalid_version.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,8 @@
+# RUN: yaml2obj %s | not obj2yaml 2>&1 | FileCheck %s
+
+--- !WASM
+FileHeader:
+  Version:         0x00000002
+...
+
+# CHECK: Error: 'Invalid data was encountered while parsing the file'

Added: llvm/trunk/test/ObjectYAML/wasm/import_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/import_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/import_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/import_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,41 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - ReturnType:      I32
+        ParamTypes:
+          - I32
+  - Type:            IMPORT
+    Imports:         
+      - Module:          foo
+        Field:           bar
+        Kind:            FUNCTION
+        SigIndex:        0
+      - Module:          fiz
+        Field:           baz
+        Kind:            GLOBAL
+        GlobalType:      I32
+        GlobalMutable:   false
+  - Type:            FUNCTION
+    FunctionTypes:
+      - 0
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:   - Type:            IMPORT
+# CHECK:     Imports:         
+# CHECK:       - Module:          foo
+# CHECK:         Field:           bar
+# CHECK:         Kind:            FUNCTION
+# CHECK:         SigIndex:        0
+# CHECK:       - Module:          fiz
+# CHECK:         Field:           baz
+# CHECK:         Kind:            GLOBAL
+# CHECK:         GlobalType:      I32
+# CHECK:         GlobalMutable:   false
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/memory_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/memory_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/memory_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/memory_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,23 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            MEMORY
+    Memories:         
+      - Flags:           0x00000001
+        Initial:         0x00000002
+        Maximum:         0x000000FF
+      - Initial:         0x00000003
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:   - Type:            MEMORY
+# CHECK:     Memories:         
+# CHECK:       - Flags:            0x00000001
+# CHECK:         Initial:          0x00000002
+# CHECK:         Maximum:          0x000000FF
+# CHECK:       - Initial:          0x00000003
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/start_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/start_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/start_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/start_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,15 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            START
+    StartFunction:   1
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:  - Type:            START
+# CHECK:    StartFunction:   1
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/table_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/table_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/table_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/table_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,25 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            TABLE
+    Tables:         
+      - ElemType:        ANYFUNC
+        Limits:
+          Flags:           0x00000001
+          Initial:         0x00000010
+          Maximum:         0x00000011
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:  - Type:            TABLE
+# CHECK:    Tables:         
+# CHECK:      - ElemType:        ANYFUNC
+# CHECK:        Limits:
+# CHECK:          Flags:           0x00000001
+# CHECK:          Initial:         0x00000010
+# CHECK:          Maximum:         0x00000011
+# CHECK: ...

Added: llvm/trunk/test/ObjectYAML/wasm/type_section.yaml
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ObjectYAML/wasm/type_section.yaml?rev=299101&view=auto
==============================================================================
--- llvm/trunk/test/ObjectYAML/wasm/type_section.yaml (added)
+++ llvm/trunk/test/ObjectYAML/wasm/type_section.yaml Thu Mar 30 14:44:09 2017
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %s | obj2yaml | FileCheck %s
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+  - Type:            TYPE
+    Signatures:
+      - ReturnType:      I32
+        ParamTypes:
+          - F32
+          - F32
+      - ReturnType:      I64
+        ParamTypes:
+          - F64
+          - F64
+...
+# CHECK: --- !WASM
+# CHECK: FileHeader:
+# CHECK:   Version:           0x00000001
+# CHECK: Sections:
+# CHECK:  - Type:            TYPE
+# CHECK:    Signatures:
+# CHECK:      - Index:           0
+# CHECK:        ReturnType:      I32
+# CHECK:        ParamTypes:
+# CHECK:          - F32
+# CHECK:          - F32
+# CHECK:      - Index:           1
+# CHECK:        ReturnType:      I64
+# CHECK:        ParamTypes:
+# CHECK:          - F64
+# CHECK:          - F64
+# CHECK: ...

Modified: llvm/trunk/test/tools/llvm-objdump/Inputs/test.wasm
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/test.wasm?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
Binary files llvm/trunk/test/tools/llvm-objdump/Inputs/test.wasm (original) and llvm/trunk/test/tools/llvm-objdump/Inputs/test.wasm Thu Mar 30 14:44:09 2017 differ

Modified: llvm/trunk/test/tools/llvm-objdump/wasm.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/wasm.txt?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/wasm.txt (original)
+++ llvm/trunk/test/tools/llvm-objdump/wasm.txt Thu Mar 30 14:44:09 2017
@@ -9,7 +9,7 @@
 # CHECK:   4 EXPORT        0000000e 0000000000000000 
 # CHECK:   5 ELEM          00000007 0000000000000000 
 # CHECK:   6 CODE          0000002a 0000000000000000 TEXT 
-# CHECK:   7 name          0000002c 0000000000000000 
+# CHECK:   7 name          0000003c 0000000000000000 
 
 # RUN: llvm-objdump -p %p/Inputs/test.wasm | FileCheck %s -check-prefix CHECK-HEADER
 

Modified: llvm/trunk/test/tools/llvm-readobj/Inputs/trivial.obj.wasm
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/Inputs/trivial.obj.wasm?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
Binary files llvm/trunk/test/tools/llvm-readobj/Inputs/trivial.obj.wasm (original) and llvm/trunk/test/tools/llvm-readobj/Inputs/trivial.obj.wasm Thu Mar 30 14:44:09 2017 differ

Modified: llvm/trunk/test/tools/llvm-readobj/sections.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-readobj/sections.test?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-readobj/sections.test (original)
+++ llvm/trunk/test/tools/llvm-readobj/sections.test Thu Mar 30 14:44:09 2017
@@ -531,7 +531,7 @@ WASM-NEXT:     Offset: 75
 WASM-NEXT:   }
 WASM-NEXT:   Section {
 WASM-NEXT:     Type: CUSTOM (0x0)
-WASM-NEXT:     Size: 44
+WASM-NEXT:     Size: 60
 WASM-NEXT:     Offset: 119
 WASM-NEXT:     Name: name
 WASM-NEXT:   }

Modified: llvm/trunk/tools/llvm-readobj/WasmDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/WasmDumper.cpp?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/WasmDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/WasmDumper.cpp Thu Mar 30 14:44:09 2017
@@ -55,14 +55,14 @@ public:
   void printSections() override {
     ListScope Group(W, "Sections");
     for (const SectionRef &Section : Obj->sections()) {
-      const wasm::WasmSection *WasmSec = Obj->getWasmSection(Section);
+      const WasmSection &WasmSec = Obj->getWasmSection(Section);
       DictScope SectionD(W, "Section");
-      const char *Type = wasmSectionTypeToString(WasmSec->Type);
-      W.printHex("Type", Type, WasmSec->Type);
-      W.printNumber("Size", (uint64_t)WasmSec->Content.size());
-      W.printNumber("Offset", WasmSec->Offset);
-      if (WasmSec->Type == wasm::WASM_SEC_CUSTOM) {
-        W.printString("Name", WasmSec->Name);
+      const char *Type = wasmSectionTypeToString(WasmSec.Type);
+      W.printHex("Type", Type, WasmSec.Type);
+      W.printNumber("Size", (uint64_t)WasmSec.Content.size());
+      W.printNumber("Offset", WasmSec.Offset);
+      if (WasmSec.Type == wasm::WASM_SEC_CUSTOM) {
+        W.printString("Name", WasmSec.Name);
       }
     }
   }

Modified: llvm/trunk/tools/obj2yaml/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/CMakeLists.txt?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/CMakeLists.txt (original)
+++ llvm/trunk/tools/obj2yaml/CMakeLists.txt Thu Mar 30 14:44:09 2017
@@ -11,5 +11,6 @@ add_llvm_tool(obj2yaml
   dwarf2yaml.cpp
   elf2yaml.cpp
   macho2yaml.cpp
+  wasm2yaml.cpp
   Error.cpp
   )

Modified: llvm/trunk/tools/obj2yaml/obj2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/obj2yaml.cpp?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/obj2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/obj2yaml.cpp Thu Mar 30 14:44:09 2017
@@ -24,6 +24,8 @@ static std::error_code dumpObject(const
     return coff2yaml(outs(), cast<COFFObjectFile>(Obj));
   if (Obj.isELF())
     return elf2yaml(outs(), Obj);
+  if (Obj.isWasm())
+    return wasm2yaml(outs(), cast<WasmObjectFile>(Obj));
 
   return obj2yaml_error::unsupported_obj_file_format;
 }

Modified: llvm/trunk/tools/obj2yaml/obj2yaml.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/obj2yaml.h?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/obj2yaml.h (original)
+++ llvm/trunk/tools/obj2yaml/obj2yaml.h Thu Mar 30 14:44:09 2017
@@ -14,6 +14,7 @@
 #define LLVM_TOOLS_OBJ2YAML_OBJ2YAML_H
 
 #include "llvm/Object/COFF.h"
+#include "llvm/Object/Wasm.h"
 #include "llvm/Support/raw_ostream.h"
 #include <system_error>
 
@@ -23,6 +24,8 @@ std::error_code elf2yaml(llvm::raw_ostre
                          const llvm::object::ObjectFile &Obj);
 std::error_code macho2yaml(llvm::raw_ostream &Out,
                            const llvm::object::Binary &Obj);
+std::error_code wasm2yaml(llvm::raw_ostream &Out,
+                          const llvm::object::WasmObjectFile &Obj);
 
 // Forward decls for dwarf2yaml
 namespace llvm {

Added: llvm/trunk/tools/obj2yaml/wasm2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/wasm2yaml.cpp?rev=299101&view=auto
==============================================================================
--- llvm/trunk/tools/obj2yaml/wasm2yaml.cpp (added)
+++ llvm/trunk/tools/obj2yaml/wasm2yaml.cpp Thu Mar 30 14:44:09 2017
@@ -0,0 +1,219 @@
+//===------ utils/wasm2yaml.cpp - obj2yaml conversion tool ------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "obj2yaml.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/ObjectYAML/WasmYAML.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/YAMLTraits.h"
+
+using namespace llvm;
+
+namespace {
+
+class WasmDumper {
+  const object::WasmObjectFile &Obj;
+
+public:
+  WasmDumper(const object::WasmObjectFile &O) : Obj(O) {}
+  ErrorOr<WasmYAML::Object *> dump();
+};
+
+ErrorOr<WasmYAML::Object *> WasmDumper::dump() {
+  auto Y = make_unique<WasmYAML::Object>();
+
+  // Dump header
+  Y->Header.Version = Obj.getHeader().Version;
+
+  // Dump sections
+  for (const auto &Sec : Obj.sections()) {
+    const object::WasmSection &WasmSec = Obj.getWasmSection(Sec);
+    std::unique_ptr<WasmYAML::Section> S;
+    switch (WasmSec.Type) {
+    case wasm::WASM_SEC_CUSTOM: {
+      if (WasmSec.Name.startswith("reloc.")) {
+        // Relocations are attached the sections they apply to rather than
+        // being represented as a custom section in the YAML output.
+        continue;
+      }
+      auto CustomSec = make_unique<WasmYAML::CustomSection>();
+      CustomSec->Name = WasmSec.Name;
+      CustomSec->Payload = yaml::BinaryRef(WasmSec.Content);
+      S = std::move(CustomSec);
+      break;
+    }
+    case wasm::WASM_SEC_TYPE: {
+      auto TypeSec = make_unique<WasmYAML::TypeSection>();
+      uint32_t Index = 0;
+      for (const auto &FunctionSig : Obj.types()) {
+        WasmYAML::Signature Sig;
+        Sig.Index = Index++;
+        Sig.ReturnType = FunctionSig.ReturnType;
+        for (const auto &ParamType : FunctionSig.ParamTypes)
+          Sig.ParamTypes.push_back(ParamType);
+        TypeSec->Signatures.push_back(Sig);
+      }
+      S = std::move(TypeSec);
+      break;
+    }
+    case wasm::WASM_SEC_IMPORT: {
+      auto ImportSec = make_unique<WasmYAML::ImportSection>();
+      for (auto &Import : Obj.imports()) {
+        WasmYAML::Import Ex;
+        Ex.Module = Import.Module;
+        Ex.Field = Import.Field;
+        Ex.Kind = Import.Kind;
+        if (Ex.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
+          Ex.SigIndex = Import.SigIndex;
+        } else if (Ex.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
+          Ex.GlobalType = Import.GlobalType;
+          Ex.GlobalMutable = Import.GlobalMutable;
+        }
+        ImportSec->Imports.push_back(Ex);
+      }
+      S = std::move(ImportSec);
+      break;
+    }
+    case wasm::WASM_SEC_FUNCTION: {
+      auto FuncSec = make_unique<WasmYAML::FunctionSection>();
+      for (const auto &Func : Obj.functionTypes()) {
+        FuncSec->FunctionTypes.push_back(Func);
+      }
+      S = std::move(FuncSec);
+      break;
+    }
+    case wasm::WASM_SEC_TABLE: {
+      auto TableSec = make_unique<WasmYAML::TableSection>();
+      for (auto &Table : Obj.tables()) {
+        WasmYAML::Table T;
+        T.ElemType = Table.ElemType;
+        T.TableLimits.Flags = Table.Limits.Flags;
+        T.TableLimits.Initial = Table.Limits.Initial;
+        T.TableLimits.Maximum = Table.Limits.Maximum;
+        TableSec->Tables.push_back(T);
+      }
+      S = std::move(TableSec);
+      break;
+    }
+    case wasm::WASM_SEC_MEMORY: {
+      auto MemorySec = make_unique<WasmYAML::MemorySection>();
+      for (auto &Memory : Obj.memories()) {
+        WasmYAML::Limits L;
+        L.Flags = Memory.Flags;
+        L.Initial = Memory.Initial;
+        L.Maximum = Memory.Maximum;
+        MemorySec->Memories.push_back(L);
+      }
+      S = std::move(MemorySec);
+      break;
+    }
+    case wasm::WASM_SEC_GLOBAL: {
+      auto GlobalSec = make_unique<WasmYAML::GlobalSection>();
+      for (auto &Global : Obj.globals()) {
+        WasmYAML::Global G;
+        G.Type = Global.Type;
+        G.Mutable = Global.Mutable;
+        G.InitExpr = Global.InitExpr;
+        GlobalSec->Globals.push_back(G);
+      }
+      S = std::move(GlobalSec);
+      break;
+    }
+    case wasm::WASM_SEC_START: {
+      auto StartSec = make_unique<WasmYAML::StartSection>();
+      StartSec->StartFunction = Obj.startFunction();
+      S = std::move(StartSec);
+      break;
+    }
+    case wasm::WASM_SEC_EXPORT: {
+      auto ExportSec = make_unique<WasmYAML::ExportSection>();
+      for (auto &Export : Obj.exports()) {
+        WasmYAML::Export Ex;
+        Ex.Name = Export.Name;
+        Ex.Kind = Export.Kind;
+        Ex.Index = Export.Index;
+        ExportSec->Exports.push_back(Ex);
+      }
+      S = std::move(ExportSec);
+      break;
+    }
+    case wasm::WASM_SEC_ELEM: {
+      auto ElemSec = make_unique<WasmYAML::ElemSection>();
+      for (auto &Segment : Obj.elements()) {
+        WasmYAML::ElemSegment Seg;
+        Seg.TableIndex = Segment.TableIndex;
+        Seg.Offset = Segment.Offset;
+        for (auto &Func : Segment.Functions) {
+          Seg.Functions.push_back(Func);
+        }
+        ElemSec->Segments.push_back(Seg);
+      }
+      S = std::move(ElemSec);
+      break;
+    }
+    case wasm::WASM_SEC_CODE: {
+      auto CodeSec = make_unique<WasmYAML::CodeSection>();
+      for (auto &Func : Obj.functions()) {
+        WasmYAML::Function Function;
+        for (auto &Local : Func.Locals) {
+          WasmYAML::LocalDecl LocalDecl;
+          LocalDecl.Type = Local.Type;
+          LocalDecl.Count = Local.Count;
+          Function.Locals.push_back(LocalDecl);
+        }
+        Function.Body = yaml::BinaryRef(Func.Body);
+        CodeSec->Functions.push_back(Function);
+      }
+      S = std::move(CodeSec);
+      break;
+    }
+    case wasm::WASM_SEC_DATA: {
+      auto DataSec = make_unique<WasmYAML::DataSection>();
+      for (auto &Segment : Obj.dataSegments()) {
+        WasmYAML::DataSegment Seg;
+        Seg.Index = Segment.Index;
+        Seg.Offset = Segment.Offset;
+        Seg.Content = yaml::BinaryRef(Segment.Content);
+        DataSec->Segments.push_back(Seg);
+      }
+      S = std::move(DataSec);
+      break;
+    }
+    default:
+      llvm_unreachable("Unknown section type");
+      break;
+    }
+    for (const wasm::WasmRelocation &Reloc: WasmSec.Relocations) {
+      WasmYAML::Relocation R;
+      R.Type = Reloc.Type;
+      R.Index = Reloc.Index;
+      R.Offset = Reloc.Offset;
+      R.Addend = Reloc.Addend;
+      S->Relocations.push_back(R);
+    }
+    Y->Sections.push_back(std::move(S));
+  }
+
+  return Y.release();
+}
+
+} // namespace
+
+std::error_code wasm2yaml(raw_ostream &Out, const object::WasmObjectFile &Obj) {
+  WasmDumper Dumper(Obj);
+  ErrorOr<WasmYAML::Object *> YAMLOrErr = Dumper.dump();
+  if (std::error_code EC = YAMLOrErr.getError())
+    return EC;
+
+  std::unique_ptr<WasmYAML::Object> YAML(YAMLOrErr.get());
+  yaml::Output Yout(Out);
+  Yout << *YAML;
+
+  return std::error_code();
+}

Modified: llvm/trunk/tools/yaml2obj/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/CMakeLists.txt?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/CMakeLists.txt (original)
+++ llvm/trunk/tools/yaml2obj/CMakeLists.txt Thu Mar 30 14:44:09 2017
@@ -10,4 +10,5 @@ add_llvm_tool(yaml2obj
   yaml2coff.cpp
   yaml2elf.cpp
   yaml2macho.cpp
+  yaml2wasm.cpp
   )

Modified: llvm/trunk/tools/yaml2obj/yaml2obj.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2obj.cpp?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2obj.cpp (original)
+++ llvm/trunk/tools/yaml2obj/yaml2obj.cpp Thu Mar 30 14:44:09 2017
@@ -57,6 +57,8 @@ static int convertYAML(yaml::Input &YIn,
         return yaml2coff(*Doc.Coff, Out);
       if (Doc.MachO || Doc.FatMachO)
         return yaml2macho(Doc, Out);
+      if (Doc.Wasm)
+        return yaml2wasm(*Doc.Wasm, Out);
       errs() << "yaml2obj: Unknown document type!\n";
       return 1;
     }

Modified: llvm/trunk/tools/yaml2obj/yaml2obj.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2obj.h?rev=299101&r1=299100&r2=299101&view=diff
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2obj.h (original)
+++ llvm/trunk/tools/yaml2obj/yaml2obj.h Thu Mar 30 14:44:09 2017
@@ -23,6 +23,10 @@ namespace ELFYAML {
 struct Object;
 }
 
+namespace WasmYAML {
+struct Object;
+}
+
 namespace yaml {
 class Input;
 struct YamlObjectFile;
@@ -32,5 +36,6 @@ struct YamlObjectFile;
 int yaml2coff(llvm::COFFYAML::Object &Doc, llvm::raw_ostream &Out);
 int yaml2elf(llvm::ELFYAML::Object &Doc, llvm::raw_ostream &Out);
 int yaml2macho(llvm::yaml::YamlObjectFile &Doc, llvm::raw_ostream &Out);
+int yaml2wasm(llvm::WasmYAML::Object &Doc, llvm::raw_ostream &Out);
 
 #endif

Added: llvm/trunk/tools/yaml2obj/yaml2wasm.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/yaml2obj/yaml2wasm.cpp?rev=299101&view=auto
==============================================================================
--- llvm/trunk/tools/yaml2obj/yaml2wasm.cpp (added)
+++ llvm/trunk/tools/yaml2obj/yaml2wasm.cpp Thu Mar 30 14:44:09 2017
@@ -0,0 +1,377 @@
+//===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief The Wasm component of yaml2obj.
+///
+//===----------------------------------------------------------------------===//
+//
+#include "yaml2obj.h"
+#include "llvm/Object/Wasm.h"
+#include "llvm/ObjectYAML/ObjectYAML.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/LEB128.h"
+
+using namespace llvm;
+
+/// This parses a yaml stream that represents a Wasm object file.
+/// See docs/yaml2obj for the yaml scheema.
+class WasmWriter {
+public:
+  WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
+  int writeWasm(raw_ostream &OS);
+  int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
+  int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
+
+private:
+  WasmYAML::Object &Obj;
+};
+
+static int writeUint64(raw_ostream &OS, uint64_t Value) {
+  char Data[sizeof(Value)];
+  support::endian::write64le(Data, Value);
+  OS.write(Data, sizeof(Data));
+  return 0;
+}
+
+static int writeUint32(raw_ostream &OS, uint32_t Value) {
+  char Data[sizeof(Value)];
+  support::endian::write32le(Data, Value);
+  OS.write(Data, sizeof(Data));
+  return 0;
+}
+
+static int writeUint8(raw_ostream &OS, uint8_t Value) {
+  char Data[sizeof(Value)];
+  memcpy(Data, &Value, sizeof(Data));
+  OS.write(Data, sizeof(Data));
+  return 0;
+}
+
+static int writeStringRef(StringRef &Str, raw_ostream &OS) {
+  encodeULEB128(Str.size(), OS);
+  OS << Str;
+  return 0;
+}
+
+static int writeLimits(WasmYAML::Limits Lim, raw_ostream &OS) {
+  encodeULEB128(Lim.Flags, OS);
+  encodeULEB128(Lim.Initial, OS);
+  if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
+    encodeULEB128(Lim.Maximum, OS);
+  return 0;
+}
+
+static int writeInitExpr(wasm::WasmInitExpr InitExpr, raw_ostream &OS) {
+  writeUint8(OS, InitExpr.Opcode);
+  switch (InitExpr.Opcode) {
+  case wasm::WASM_OPCODE_I32_CONST:
+    encodeSLEB128(InitExpr.Value.Int32, OS);
+    break;
+  case wasm::WASM_OPCODE_I64_CONST:
+    encodeSLEB128(InitExpr.Value.Int64, OS);
+    break;
+  case wasm::WASM_OPCODE_F32_CONST:
+    writeUint32(OS, InitExpr.Value.Float32);
+    break;
+  case wasm::WASM_OPCODE_F64_CONST:
+    writeUint64(OS, InitExpr.Value.Float64);
+    break;
+  case wasm::WASM_OPCODE_GET_GLOBAL:
+    encodeULEB128(InitExpr.Value.Global, OS);
+    break;
+  default:
+    errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode;
+    return 1;
+  }
+  writeUint8(OS, wasm::WASM_OPCODE_END);
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::CustomSection &Section) {
+  // writeStringRef(Section.Name, OS);
+  // encodeULEB128(Section.Payload.binary_size(), OS);
+  Section.Payload.writeAsBinary(OS);
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::TypeSection &Section) {
+  encodeULEB128(Section.Signatures.size(), OS);
+  for (auto &Sig : Section.Signatures) {
+    encodeSLEB128(Sig.Form, OS);
+    encodeULEB128(Sig.ParamTypes.size(), OS);
+    for (auto ParamType : Sig.ParamTypes)
+      encodeSLEB128(ParamType, OS);
+    if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
+      encodeSLEB128(0, OS);
+    } else {
+      encodeULEB128(1, OS);
+      encodeSLEB128(Sig.ReturnType, OS);
+    }
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::ImportSection &Section) {
+  encodeULEB128(Section.Imports.size(), OS);
+  for (auto &Import : Section.Imports) {
+    writeStringRef(Import.Module, OS);
+    writeStringRef(Import.Field, OS);
+    encodeULEB128(Import.Kind, OS);
+    switch (Import.Kind) {
+    case wasm::WASM_EXTERNAL_FUNCTION:
+      encodeULEB128(Import.SigIndex, OS);
+      break;
+    case wasm::WASM_EXTERNAL_GLOBAL:
+      encodeSLEB128(Import.GlobalType, OS);
+      writeUint8(OS, Import.GlobalMutable);
+      break;
+    default:
+      errs() << "Unknown import type: " << Import.Kind;
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::FunctionSection &Section) {
+  encodeULEB128(Section.FunctionTypes.size(), OS);
+  for (uint32_t FuncType : Section.FunctionTypes) {
+    encodeULEB128(FuncType, OS);
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::ExportSection &Section) {
+  encodeULEB128(Section.Exports.size(), OS);
+  for (auto &Export : Section.Exports) {
+    writeStringRef(Export.Name, OS);
+    encodeULEB128(Export.Kind, OS);
+    encodeULEB128(Export.Index, OS);
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::StartSection &Section) {
+  encodeULEB128(Section.StartFunction, OS);
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::TableSection &Section) {
+  encodeULEB128(Section.Tables.size(), OS);
+  for (auto &Table : Section.Tables) {
+    encodeSLEB128(Table.ElemType, OS);
+    writeLimits(Table.TableLimits, OS);
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::MemorySection &Section) {
+  encodeULEB128(Section.Memories.size(), OS);
+  for (auto &Mem : Section.Memories) {
+    writeLimits(Mem, OS);
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::GlobalSection &Section) {
+  encodeULEB128(Section.Globals.size(), OS);
+  for (auto &Global : Section.Globals) {
+    encodeSLEB128(Global.Type, OS);
+    writeUint8(OS, Global.Mutable);
+    writeInitExpr(Global.InitExpr, OS);
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::ElemSection &Section) {
+  encodeULEB128(Section.Segments.size(), OS);
+  for (auto &Segment : Section.Segments) {
+    encodeULEB128(Segment.TableIndex, OS);
+    writeInitExpr(Segment.Offset, OS);
+
+    encodeULEB128(Segment.Functions.size(), OS);
+    for (auto &Function : Segment.Functions) {
+      encodeULEB128(Function, OS);
+    }
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::CodeSection &Section) {
+  encodeULEB128(Section.Functions.size(), OS);
+  for (auto &Func : Section.Functions) {
+    std::string OutString;
+    raw_string_ostream StringStream(OutString);
+
+    encodeULEB128(Func.Locals.size(), StringStream);
+    for (auto &LocalDecl : Func.Locals) {
+      encodeULEB128(LocalDecl.Count, StringStream);
+      encodeSLEB128(LocalDecl.Type, StringStream);
+    }
+
+    Func.Body.writeAsBinary(StringStream);
+
+    // Write the section size followed by the content
+    StringStream.flush();
+    encodeULEB128(OutString.size(), OS);
+    OS << OutString;
+  }
+  return 0;
+}
+
+int WasmWriter::writeSectionContent(raw_ostream &OS,
+                                    WasmYAML::DataSection &Section) {
+  encodeULEB128(Section.Segments.size(), OS);
+  for (auto &Segment : Section.Segments) {
+    encodeULEB128(Segment.Index, OS);
+    writeInitExpr(Segment.Offset, OS);
+    encodeULEB128(Segment.Content.binary_size(), OS);
+    Segment.Content.writeAsBinary(OS);
+  }
+  return 0;
+}
+
+int WasmWriter::writeRelocSection(raw_ostream &OS,
+                                  WasmYAML::Section &Sec) {
+  StringRef Name;
+  switch (Sec.Type) {
+    case wasm::WASM_SEC_CODE:
+      Name = "reloc.CODE";
+      break;
+    case wasm::WASM_SEC_DATA:
+      Name = "reloc.DATA";
+      break;
+    default:
+      llvm_unreachable("not yet implemented");
+      return 1;
+  }
+
+  writeStringRef(Name, OS);
+  encodeULEB128(Sec.Type, OS);
+  encodeULEB128(Sec.Relocations.size(), OS);
+
+  for (auto Reloc: Sec.Relocations) {
+    encodeULEB128(Reloc.Type, OS);
+    encodeULEB128(Reloc.Offset, OS);
+    encodeULEB128(Reloc.Index, OS);
+    switch (Reloc.Type) {
+      case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
+      case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
+      case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
+        encodeULEB128(Reloc.Addend, OS);
+    }
+  }
+  return 0;
+}
+
+
+int WasmWriter::writeWasm(raw_ostream &OS) {
+  // Write headers
+  OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
+  writeUint32(OS, Obj.Header.Version);
+
+  // Write each section
+  for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
+    encodeULEB128(Sec->Type, OS);
+
+    std::string OutString;
+    raw_string_ostream StringStream(OutString);
+    if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
+      if (auto Err = writeSectionContent(StringStream, *S))
+        return Err;
+    } else {
+      errs() << "Unknown section type: " << Sec->Type << "\n";
+      return 1;
+    }
+    StringStream.flush();
+
+    // Write the section size followed by the content
+    encodeULEB128(OutString.size(), OS);
+    OS << OutString;
+  }
+
+  // write reloc sections for any section that have relocations
+  for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
+    if (Sec->Relocations.empty())
+      continue;
+
+    encodeULEB128(wasm::WASM_SEC_CUSTOM, OS);
+    std::string OutString;
+    raw_string_ostream StringStream(OutString);
+    writeRelocSection(StringStream, *Sec);
+    StringStream.flush();
+
+    encodeULEB128(OutString.size(), OS);
+    OS << OutString;
+  }
+
+  return 0;
+}
+
+int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
+  WasmWriter Writer(Doc);
+
+  return Writer.writeWasm(Out);
+}




More information about the llvm-commits mailing list