| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,5 +6,6 @@ add_llvm_library(LLVMObjectYAML | |
| ELFYAML.cpp | ||
| MachOYAML.cpp | ||
| ObjectYAML.cpp | ||
| WasmYAML.cpp | ||
| YAML.cpp | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # RUN: yaml2obj %s | obj2yaml | FileCheck %s | ||
| --- !WASM | ||
| FileHeader: | ||
| Version: 0x00000001 | ||
| ... | ||
| # CHECK: --- !WASM | ||
| # CHECK: FileHeader: | ||
| # CHECK: Version: 0x00000001 | ||
| # CHECK: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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: ... |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,5 +11,6 @@ add_llvm_tool(obj2yaml | |
| dwarf2yaml.cpp | ||
| elf2yaml.cpp | ||
| macho2yaml.cpp | ||
| wasm2yaml.cpp | ||
| Error.cpp | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,4 +10,5 @@ add_llvm_tool(yaml2obj | |
| yaml2coff.cpp | ||
| yaml2elf.cpp | ||
| yaml2macho.cpp | ||
| yaml2wasm.cpp | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
| } |