xref: /freebsd-src/contrib/llvm-project/llvm/lib/ObjectYAML/WasmEmitter.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
18bcb0991SDimitry Andric //===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
28bcb0991SDimitry Andric //
38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68bcb0991SDimitry Andric //
78bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
88bcb0991SDimitry Andric ///
98bcb0991SDimitry Andric /// \file
108bcb0991SDimitry Andric /// The Wasm component of yaml2obj.
118bcb0991SDimitry Andric ///
128bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
138bcb0991SDimitry Andric //
148bcb0991SDimitry Andric 
158bcb0991SDimitry Andric #include "llvm/Object/Wasm.h"
168bcb0991SDimitry Andric #include "llvm/ObjectYAML/ObjectYAML.h"
178bcb0991SDimitry Andric #include "llvm/ObjectYAML/yaml2obj.h"
188bcb0991SDimitry Andric #include "llvm/Support/Endian.h"
198bcb0991SDimitry Andric #include "llvm/Support/LEB128.h"
208bcb0991SDimitry Andric 
218bcb0991SDimitry Andric using namespace llvm;
228bcb0991SDimitry Andric 
238bcb0991SDimitry Andric namespace {
248bcb0991SDimitry Andric /// This parses a yaml stream that represents a Wasm object file.
258bcb0991SDimitry Andric /// See docs/yaml2obj for the yaml scheema.
268bcb0991SDimitry Andric class WasmWriter {
278bcb0991SDimitry Andric public:
288bcb0991SDimitry Andric   WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)
298bcb0991SDimitry Andric       : Obj(Obj), ErrHandler(EH) {}
308bcb0991SDimitry Andric   bool writeWasm(raw_ostream &OS);
318bcb0991SDimitry Andric 
328bcb0991SDimitry Andric private:
338bcb0991SDimitry Andric   void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
348bcb0991SDimitry Andric                          uint32_t SectionIndex);
358bcb0991SDimitry Andric 
368bcb0991SDimitry Andric   void writeInitExpr(raw_ostream &OS, const wasm::WasmInitExpr &InitExpr);
378bcb0991SDimitry Andric 
388bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
398bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
408bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
418bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
428bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
438bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
44fe6060f1SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::TagSection &Section);
455ffd83dbSDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
468bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
478bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
488bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
498bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
508bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
518bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
528bcb0991SDimitry Andric 
538bcb0991SDimitry Andric   // Custom section types
548bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
558bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
568bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
578bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
588bcb0991SDimitry Andric   void writeSectionContent(raw_ostream &OS,
598bcb0991SDimitry Andric                           WasmYAML::TargetFeaturesSection &Section);
608bcb0991SDimitry Andric   WasmYAML::Object &Obj;
618bcb0991SDimitry Andric   uint32_t NumImportedFunctions = 0;
628bcb0991SDimitry Andric   uint32_t NumImportedGlobals = 0;
63e8d8bef9SDimitry Andric   uint32_t NumImportedTables = 0;
64fe6060f1SDimitry Andric   uint32_t NumImportedTags = 0;
658bcb0991SDimitry Andric 
668bcb0991SDimitry Andric   bool HasError = false;
678bcb0991SDimitry Andric   yaml::ErrorHandler ErrHandler;
688bcb0991SDimitry Andric   void reportError(const Twine &Msg);
698bcb0991SDimitry Andric };
708bcb0991SDimitry Andric 
718bcb0991SDimitry Andric class SubSectionWriter {
728bcb0991SDimitry Andric   raw_ostream &OS;
738bcb0991SDimitry Andric   std::string OutString;
748bcb0991SDimitry Andric   raw_string_ostream StringStream;
758bcb0991SDimitry Andric 
768bcb0991SDimitry Andric public:
778bcb0991SDimitry Andric   SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
788bcb0991SDimitry Andric 
798bcb0991SDimitry Andric   void done() {
808bcb0991SDimitry Andric     StringStream.flush();
818bcb0991SDimitry Andric     encodeULEB128(OutString.size(), OS);
828bcb0991SDimitry Andric     OS << OutString;
838bcb0991SDimitry Andric     OutString.clear();
848bcb0991SDimitry Andric   }
858bcb0991SDimitry Andric 
868bcb0991SDimitry Andric   raw_ostream &getStream() { return StringStream; }
878bcb0991SDimitry Andric };
888bcb0991SDimitry Andric 
898bcb0991SDimitry Andric } // end anonymous namespace
908bcb0991SDimitry Andric 
918bcb0991SDimitry Andric static int writeUint64(raw_ostream &OS, uint64_t Value) {
928bcb0991SDimitry Andric   char Data[sizeof(Value)];
938bcb0991SDimitry Andric   support::endian::write64le(Data, Value);
948bcb0991SDimitry Andric   OS.write(Data, sizeof(Data));
958bcb0991SDimitry Andric   return 0;
968bcb0991SDimitry Andric }
978bcb0991SDimitry Andric 
988bcb0991SDimitry Andric static int writeUint32(raw_ostream &OS, uint32_t Value) {
998bcb0991SDimitry Andric   char Data[sizeof(Value)];
1008bcb0991SDimitry Andric   support::endian::write32le(Data, Value);
1018bcb0991SDimitry Andric   OS.write(Data, sizeof(Data));
1028bcb0991SDimitry Andric   return 0;
1038bcb0991SDimitry Andric }
1048bcb0991SDimitry Andric 
1058bcb0991SDimitry Andric static int writeUint8(raw_ostream &OS, uint8_t Value) {
1068bcb0991SDimitry Andric   char Data[sizeof(Value)];
1078bcb0991SDimitry Andric   memcpy(Data, &Value, sizeof(Data));
1088bcb0991SDimitry Andric   OS.write(Data, sizeof(Data));
1098bcb0991SDimitry Andric   return 0;
1108bcb0991SDimitry Andric }
1118bcb0991SDimitry Andric 
1128bcb0991SDimitry Andric static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
1138bcb0991SDimitry Andric   encodeULEB128(Str.size(), OS);
1148bcb0991SDimitry Andric   OS << Str;
1158bcb0991SDimitry Andric   return 0;
1168bcb0991SDimitry Andric }
1178bcb0991SDimitry Andric 
1188bcb0991SDimitry Andric static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
1198bcb0991SDimitry Andric   writeUint8(OS, Lim.Flags);
120fe6060f1SDimitry Andric   encodeULEB128(Lim.Minimum, OS);
1218bcb0991SDimitry Andric   if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
1228bcb0991SDimitry Andric     encodeULEB128(Lim.Maximum, OS);
1238bcb0991SDimitry Andric   return 0;
1248bcb0991SDimitry Andric }
1258bcb0991SDimitry Andric 
1268bcb0991SDimitry Andric void WasmWriter::reportError(const Twine &Msg) {
1278bcb0991SDimitry Andric   ErrHandler(Msg);
1288bcb0991SDimitry Andric   HasError = true;
1298bcb0991SDimitry Andric }
1308bcb0991SDimitry Andric 
1318bcb0991SDimitry Andric void WasmWriter::writeInitExpr(raw_ostream &OS,
1328bcb0991SDimitry Andric                                const wasm::WasmInitExpr &InitExpr) {
1338bcb0991SDimitry Andric   writeUint8(OS, InitExpr.Opcode);
1348bcb0991SDimitry Andric   switch (InitExpr.Opcode) {
1358bcb0991SDimitry Andric   case wasm::WASM_OPCODE_I32_CONST:
1368bcb0991SDimitry Andric     encodeSLEB128(InitExpr.Value.Int32, OS);
1378bcb0991SDimitry Andric     break;
1388bcb0991SDimitry Andric   case wasm::WASM_OPCODE_I64_CONST:
1398bcb0991SDimitry Andric     encodeSLEB128(InitExpr.Value.Int64, OS);
1408bcb0991SDimitry Andric     break;
1418bcb0991SDimitry Andric   case wasm::WASM_OPCODE_F32_CONST:
1428bcb0991SDimitry Andric     writeUint32(OS, InitExpr.Value.Float32);
1438bcb0991SDimitry Andric     break;
1448bcb0991SDimitry Andric   case wasm::WASM_OPCODE_F64_CONST:
1458bcb0991SDimitry Andric     writeUint64(OS, InitExpr.Value.Float64);
1468bcb0991SDimitry Andric     break;
1478bcb0991SDimitry Andric   case wasm::WASM_OPCODE_GLOBAL_GET:
1488bcb0991SDimitry Andric     encodeULEB128(InitExpr.Value.Global, OS);
1498bcb0991SDimitry Andric     break;
1508bcb0991SDimitry Andric   default:
1518bcb0991SDimitry Andric     reportError("unknown opcode in init_expr: " + Twine(InitExpr.Opcode));
1528bcb0991SDimitry Andric     return;
1538bcb0991SDimitry Andric   }
1548bcb0991SDimitry Andric   writeUint8(OS, wasm::WASM_OPCODE_END);
1558bcb0991SDimitry Andric }
1568bcb0991SDimitry Andric 
1578bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
1588bcb0991SDimitry Andric                                      WasmYAML::DylinkSection &Section) {
1598bcb0991SDimitry Andric   writeStringRef(Section.Name, OS);
160*349cc55cSDimitry Andric 
161*349cc55cSDimitry Andric   writeUint8(OS, wasm::WASM_DYLINK_MEM_INFO);
162*349cc55cSDimitry Andric   SubSectionWriter SubSection(OS);
163*349cc55cSDimitry Andric   raw_ostream &SubOS = SubSection.getStream();
164*349cc55cSDimitry Andric   encodeULEB128(Section.MemorySize, SubOS);
165*349cc55cSDimitry Andric   encodeULEB128(Section.MemoryAlignment, SubOS);
166*349cc55cSDimitry Andric   encodeULEB128(Section.TableSize, SubOS);
167*349cc55cSDimitry Andric   encodeULEB128(Section.TableAlignment, SubOS);
168*349cc55cSDimitry Andric   SubSection.done();
169*349cc55cSDimitry Andric 
170*349cc55cSDimitry Andric   if (Section.Needed.size()) {
171*349cc55cSDimitry Andric     writeUint8(OS, wasm::WASM_DYLINK_NEEDED);
172*349cc55cSDimitry Andric     raw_ostream &SubOS = SubSection.getStream();
173*349cc55cSDimitry Andric     encodeULEB128(Section.Needed.size(), SubOS);
1748bcb0991SDimitry Andric     for (StringRef Needed : Section.Needed)
175*349cc55cSDimitry Andric       writeStringRef(Needed, SubOS);
176*349cc55cSDimitry Andric     SubSection.done();
177*349cc55cSDimitry Andric   }
1788bcb0991SDimitry Andric }
1798bcb0991SDimitry Andric 
1808bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
1818bcb0991SDimitry Andric                                      WasmYAML::LinkingSection &Section) {
1828bcb0991SDimitry Andric   writeStringRef(Section.Name, OS);
1838bcb0991SDimitry Andric   encodeULEB128(Section.Version, OS);
1848bcb0991SDimitry Andric 
1858bcb0991SDimitry Andric   SubSectionWriter SubSection(OS);
1868bcb0991SDimitry Andric 
1878bcb0991SDimitry Andric   // SYMBOL_TABLE subsection
1888bcb0991SDimitry Andric   if (Section.SymbolTable.size()) {
1898bcb0991SDimitry Andric     writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
1908bcb0991SDimitry Andric 
1918bcb0991SDimitry Andric     encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
1928bcb0991SDimitry Andric #ifndef NDEBUG
1938bcb0991SDimitry Andric     uint32_t SymbolIndex = 0;
1948bcb0991SDimitry Andric #endif
1958bcb0991SDimitry Andric     for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
1968bcb0991SDimitry Andric       assert(Info.Index == SymbolIndex++);
1978bcb0991SDimitry Andric       writeUint8(SubSection.getStream(), Info.Kind);
1988bcb0991SDimitry Andric       encodeULEB128(Info.Flags, SubSection.getStream());
1998bcb0991SDimitry Andric       switch (Info.Kind) {
2008bcb0991SDimitry Andric       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
2018bcb0991SDimitry Andric       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
202e8d8bef9SDimitry Andric       case wasm::WASM_SYMBOL_TYPE_TABLE:
203fe6060f1SDimitry Andric       case wasm::WASM_SYMBOL_TYPE_TAG:
2048bcb0991SDimitry Andric         encodeULEB128(Info.ElementIndex, SubSection.getStream());
2058bcb0991SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
2068bcb0991SDimitry Andric             (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
2078bcb0991SDimitry Andric           writeStringRef(Info.Name, SubSection.getStream());
2088bcb0991SDimitry Andric         break;
2098bcb0991SDimitry Andric       case wasm::WASM_SYMBOL_TYPE_DATA:
2108bcb0991SDimitry Andric         writeStringRef(Info.Name, SubSection.getStream());
2118bcb0991SDimitry Andric         if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
2128bcb0991SDimitry Andric           encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
2138bcb0991SDimitry Andric           encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
2148bcb0991SDimitry Andric           encodeULEB128(Info.DataRef.Size, SubSection.getStream());
2158bcb0991SDimitry Andric         }
2168bcb0991SDimitry Andric         break;
2178bcb0991SDimitry Andric       case wasm::WASM_SYMBOL_TYPE_SECTION:
2188bcb0991SDimitry Andric         encodeULEB128(Info.ElementIndex, SubSection.getStream());
2198bcb0991SDimitry Andric         break;
2208bcb0991SDimitry Andric       default:
2218bcb0991SDimitry Andric         llvm_unreachable("unexpected kind");
2228bcb0991SDimitry Andric       }
2238bcb0991SDimitry Andric     }
2248bcb0991SDimitry Andric 
2258bcb0991SDimitry Andric     SubSection.done();
2268bcb0991SDimitry Andric   }
2278bcb0991SDimitry Andric 
2288bcb0991SDimitry Andric   // SEGMENT_NAMES subsection
2298bcb0991SDimitry Andric   if (Section.SegmentInfos.size()) {
2308bcb0991SDimitry Andric     writeUint8(OS, wasm::WASM_SEGMENT_INFO);
2318bcb0991SDimitry Andric     encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
2328bcb0991SDimitry Andric     for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
2338bcb0991SDimitry Andric       writeStringRef(SegmentInfo.Name, SubSection.getStream());
2348bcb0991SDimitry Andric       encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
2358bcb0991SDimitry Andric       encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
2368bcb0991SDimitry Andric     }
2378bcb0991SDimitry Andric     SubSection.done();
2388bcb0991SDimitry Andric   }
2398bcb0991SDimitry Andric 
2408bcb0991SDimitry Andric   // INIT_FUNCS subsection
2418bcb0991SDimitry Andric   if (Section.InitFunctions.size()) {
2428bcb0991SDimitry Andric     writeUint8(OS, wasm::WASM_INIT_FUNCS);
2438bcb0991SDimitry Andric     encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
2448bcb0991SDimitry Andric     for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
2458bcb0991SDimitry Andric       encodeULEB128(Func.Priority, SubSection.getStream());
2468bcb0991SDimitry Andric       encodeULEB128(Func.Symbol, SubSection.getStream());
2478bcb0991SDimitry Andric     }
2488bcb0991SDimitry Andric     SubSection.done();
2498bcb0991SDimitry Andric   }
2508bcb0991SDimitry Andric 
2518bcb0991SDimitry Andric   // COMDAT_INFO subsection
2528bcb0991SDimitry Andric   if (Section.Comdats.size()) {
2538bcb0991SDimitry Andric     writeUint8(OS, wasm::WASM_COMDAT_INFO);
2548bcb0991SDimitry Andric     encodeULEB128(Section.Comdats.size(), SubSection.getStream());
2558bcb0991SDimitry Andric     for (const auto &C : Section.Comdats) {
2568bcb0991SDimitry Andric       writeStringRef(C.Name, SubSection.getStream());
2578bcb0991SDimitry Andric       encodeULEB128(0, SubSection.getStream()); // flags for future use
2588bcb0991SDimitry Andric       encodeULEB128(C.Entries.size(), SubSection.getStream());
2598bcb0991SDimitry Andric       for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
2608bcb0991SDimitry Andric         writeUint8(SubSection.getStream(), Entry.Kind);
2618bcb0991SDimitry Andric         encodeULEB128(Entry.Index, SubSection.getStream());
2628bcb0991SDimitry Andric       }
2638bcb0991SDimitry Andric     }
2648bcb0991SDimitry Andric     SubSection.done();
2658bcb0991SDimitry Andric   }
2668bcb0991SDimitry Andric }
2678bcb0991SDimitry Andric 
2688bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
2698bcb0991SDimitry Andric                                      WasmYAML::NameSection &Section) {
2708bcb0991SDimitry Andric   writeStringRef(Section.Name, OS);
2718bcb0991SDimitry Andric   if (Section.FunctionNames.size()) {
2728bcb0991SDimitry Andric     writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
2738bcb0991SDimitry Andric 
2748bcb0991SDimitry Andric     SubSectionWriter SubSection(OS);
2758bcb0991SDimitry Andric 
2768bcb0991SDimitry Andric     encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
2778bcb0991SDimitry Andric     for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
2788bcb0991SDimitry Andric       encodeULEB128(NameEntry.Index, SubSection.getStream());
2798bcb0991SDimitry Andric       writeStringRef(NameEntry.Name, SubSection.getStream());
2808bcb0991SDimitry Andric     }
2818bcb0991SDimitry Andric 
2828bcb0991SDimitry Andric     SubSection.done();
2838bcb0991SDimitry Andric   }
284e8d8bef9SDimitry Andric   if (Section.GlobalNames.size()) {
285e8d8bef9SDimitry Andric     writeUint8(OS, wasm::WASM_NAMES_GLOBAL);
286e8d8bef9SDimitry Andric 
287e8d8bef9SDimitry Andric     SubSectionWriter SubSection(OS);
288e8d8bef9SDimitry Andric 
289e8d8bef9SDimitry Andric     encodeULEB128(Section.GlobalNames.size(), SubSection.getStream());
290e8d8bef9SDimitry Andric     for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {
291e8d8bef9SDimitry Andric       encodeULEB128(NameEntry.Index, SubSection.getStream());
292e8d8bef9SDimitry Andric       writeStringRef(NameEntry.Name, SubSection.getStream());
293e8d8bef9SDimitry Andric     }
294e8d8bef9SDimitry Andric 
295e8d8bef9SDimitry Andric     SubSection.done();
296e8d8bef9SDimitry Andric   }
297e8d8bef9SDimitry Andric   if (Section.DataSegmentNames.size()) {
298e8d8bef9SDimitry Andric     writeUint8(OS, wasm::WASM_NAMES_DATA_SEGMENT);
299e8d8bef9SDimitry Andric 
300e8d8bef9SDimitry Andric     SubSectionWriter SubSection(OS);
301e8d8bef9SDimitry Andric 
302e8d8bef9SDimitry Andric     encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());
303e8d8bef9SDimitry Andric     for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {
304e8d8bef9SDimitry Andric       encodeULEB128(NameEntry.Index, SubSection.getStream());
305e8d8bef9SDimitry Andric       writeStringRef(NameEntry.Name, SubSection.getStream());
306e8d8bef9SDimitry Andric     }
307e8d8bef9SDimitry Andric 
308e8d8bef9SDimitry Andric     SubSection.done();
309e8d8bef9SDimitry Andric   }
3108bcb0991SDimitry Andric }
3118bcb0991SDimitry Andric 
3128bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3138bcb0991SDimitry Andric                                      WasmYAML::ProducersSection &Section) {
3148bcb0991SDimitry Andric   writeStringRef(Section.Name, OS);
3158bcb0991SDimitry Andric   int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
3168bcb0991SDimitry Andric                int(!Section.SDKs.empty());
3178bcb0991SDimitry Andric   if (Fields == 0)
3188bcb0991SDimitry Andric     return;
3198bcb0991SDimitry Andric   encodeULEB128(Fields, OS);
3208bcb0991SDimitry Andric   for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
3218bcb0991SDimitry Andric                       std::make_pair(StringRef("processed-by"), &Section.Tools),
3228bcb0991SDimitry Andric                       std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
3238bcb0991SDimitry Andric     if (Field.second->empty())
3248bcb0991SDimitry Andric       continue;
3258bcb0991SDimitry Andric     writeStringRef(Field.first, OS);
3268bcb0991SDimitry Andric     encodeULEB128(Field.second->size(), OS);
3278bcb0991SDimitry Andric     for (auto &Entry : *Field.second) {
3288bcb0991SDimitry Andric       writeStringRef(Entry.Name, OS);
3298bcb0991SDimitry Andric       writeStringRef(Entry.Version, OS);
3308bcb0991SDimitry Andric     }
3318bcb0991SDimitry Andric   }
3328bcb0991SDimitry Andric }
3338bcb0991SDimitry Andric 
3348bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3358bcb0991SDimitry Andric                                      WasmYAML::TargetFeaturesSection &Section) {
3368bcb0991SDimitry Andric   writeStringRef(Section.Name, OS);
3378bcb0991SDimitry Andric   encodeULEB128(Section.Features.size(), OS);
3388bcb0991SDimitry Andric   for (auto &E : Section.Features) {
3398bcb0991SDimitry Andric     writeUint8(OS, E.Prefix);
3408bcb0991SDimitry Andric     writeStringRef(E.Name, OS);
3418bcb0991SDimitry Andric   }
3428bcb0991SDimitry Andric }
3438bcb0991SDimitry Andric 
3448bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3458bcb0991SDimitry Andric                                      WasmYAML::CustomSection &Section) {
3468bcb0991SDimitry Andric   if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
3478bcb0991SDimitry Andric     writeSectionContent(OS, *S);
3488bcb0991SDimitry Andric   } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
3498bcb0991SDimitry Andric     writeSectionContent(OS, *S);
3508bcb0991SDimitry Andric   } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
3518bcb0991SDimitry Andric     writeSectionContent(OS, *S);
3528bcb0991SDimitry Andric   } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
3538bcb0991SDimitry Andric     writeSectionContent(OS, *S);
3548bcb0991SDimitry Andric   } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
3558bcb0991SDimitry Andric     writeSectionContent(OS, *S);
3568bcb0991SDimitry Andric   } else {
3578bcb0991SDimitry Andric     writeStringRef(Section.Name, OS);
3588bcb0991SDimitry Andric     Section.Payload.writeAsBinary(OS);
3598bcb0991SDimitry Andric   }
3608bcb0991SDimitry Andric }
3618bcb0991SDimitry Andric 
3628bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3638bcb0991SDimitry Andric                                     WasmYAML::TypeSection &Section) {
3648bcb0991SDimitry Andric   encodeULEB128(Section.Signatures.size(), OS);
3658bcb0991SDimitry Andric   uint32_t ExpectedIndex = 0;
3668bcb0991SDimitry Andric   for (const WasmYAML::Signature &Sig : Section.Signatures) {
3678bcb0991SDimitry Andric     if (Sig.Index != ExpectedIndex) {
3688bcb0991SDimitry Andric       reportError("unexpected type index: " + Twine(Sig.Index));
3698bcb0991SDimitry Andric       return;
3708bcb0991SDimitry Andric     }
3718bcb0991SDimitry Andric     ++ExpectedIndex;
3728bcb0991SDimitry Andric     writeUint8(OS, Sig.Form);
3738bcb0991SDimitry Andric     encodeULEB128(Sig.ParamTypes.size(), OS);
3748bcb0991SDimitry Andric     for (auto ParamType : Sig.ParamTypes)
3758bcb0991SDimitry Andric       writeUint8(OS, ParamType);
3768bcb0991SDimitry Andric     encodeULEB128(Sig.ReturnTypes.size(), OS);
3778bcb0991SDimitry Andric     for (auto ReturnType : Sig.ReturnTypes)
3788bcb0991SDimitry Andric       writeUint8(OS, ReturnType);
3798bcb0991SDimitry Andric   }
3808bcb0991SDimitry Andric }
3818bcb0991SDimitry Andric 
3828bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3838bcb0991SDimitry Andric                                     WasmYAML::ImportSection &Section) {
3848bcb0991SDimitry Andric   encodeULEB128(Section.Imports.size(), OS);
3858bcb0991SDimitry Andric   for (const WasmYAML::Import &Import : Section.Imports) {
3868bcb0991SDimitry Andric     writeStringRef(Import.Module, OS);
3878bcb0991SDimitry Andric     writeStringRef(Import.Field, OS);
3888bcb0991SDimitry Andric     writeUint8(OS, Import.Kind);
3898bcb0991SDimitry Andric     switch (Import.Kind) {
3908bcb0991SDimitry Andric     case wasm::WASM_EXTERNAL_FUNCTION:
3918bcb0991SDimitry Andric       encodeULEB128(Import.SigIndex, OS);
3928bcb0991SDimitry Andric       NumImportedFunctions++;
3938bcb0991SDimitry Andric       break;
3948bcb0991SDimitry Andric     case wasm::WASM_EXTERNAL_GLOBAL:
3958bcb0991SDimitry Andric       writeUint8(OS, Import.GlobalImport.Type);
3968bcb0991SDimitry Andric       writeUint8(OS, Import.GlobalImport.Mutable);
3978bcb0991SDimitry Andric       NumImportedGlobals++;
3988bcb0991SDimitry Andric       break;
399fe6060f1SDimitry Andric     case wasm::WASM_EXTERNAL_TAG:
400*349cc55cSDimitry Andric       writeUint8(OS, 0); // Reserved 'attribute' field
401*349cc55cSDimitry Andric       encodeULEB128(Import.SigIndex, OS);
402fe6060f1SDimitry Andric       NumImportedTags++;
4038bcb0991SDimitry Andric       break;
4048bcb0991SDimitry Andric     case wasm::WASM_EXTERNAL_MEMORY:
4058bcb0991SDimitry Andric       writeLimits(Import.Memory, OS);
4068bcb0991SDimitry Andric       break;
4078bcb0991SDimitry Andric     case wasm::WASM_EXTERNAL_TABLE:
4088bcb0991SDimitry Andric       writeUint8(OS, Import.TableImport.ElemType);
4098bcb0991SDimitry Andric       writeLimits(Import.TableImport.TableLimits, OS);
410e8d8bef9SDimitry Andric       NumImportedTables++;
4118bcb0991SDimitry Andric       break;
4128bcb0991SDimitry Andric     default:
4138bcb0991SDimitry Andric       reportError("unknown import type: " +Twine(Import.Kind));
4148bcb0991SDimitry Andric       return;
4158bcb0991SDimitry Andric     }
4168bcb0991SDimitry Andric   }
4178bcb0991SDimitry Andric }
4188bcb0991SDimitry Andric 
4198bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4208bcb0991SDimitry Andric                                      WasmYAML::FunctionSection &Section) {
4218bcb0991SDimitry Andric   encodeULEB128(Section.FunctionTypes.size(), OS);
4228bcb0991SDimitry Andric   for (uint32_t FuncType : Section.FunctionTypes)
4238bcb0991SDimitry Andric     encodeULEB128(FuncType, OS);
4248bcb0991SDimitry Andric }
4258bcb0991SDimitry Andric 
4268bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4278bcb0991SDimitry Andric                                     WasmYAML::ExportSection &Section) {
4288bcb0991SDimitry Andric   encodeULEB128(Section.Exports.size(), OS);
4298bcb0991SDimitry Andric   for (const WasmYAML::Export &Export : Section.Exports) {
4308bcb0991SDimitry Andric     writeStringRef(Export.Name, OS);
4318bcb0991SDimitry Andric     writeUint8(OS, Export.Kind);
4328bcb0991SDimitry Andric     encodeULEB128(Export.Index, OS);
4338bcb0991SDimitry Andric   }
4348bcb0991SDimitry Andric }
4358bcb0991SDimitry Andric 
4368bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4378bcb0991SDimitry Andric                                      WasmYAML::StartSection &Section) {
4388bcb0991SDimitry Andric   encodeULEB128(Section.StartFunction, OS);
4398bcb0991SDimitry Andric }
4408bcb0991SDimitry Andric 
4418bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4428bcb0991SDimitry Andric                                      WasmYAML::TableSection &Section) {
4438bcb0991SDimitry Andric   encodeULEB128(Section.Tables.size(), OS);
444e8d8bef9SDimitry Andric   uint32_t ExpectedIndex = NumImportedTables;
4458bcb0991SDimitry Andric   for (auto &Table : Section.Tables) {
446e8d8bef9SDimitry Andric     if (Table.Index != ExpectedIndex) {
447e8d8bef9SDimitry Andric       reportError("unexpected table index: " + Twine(Table.Index));
448e8d8bef9SDimitry Andric       return;
449e8d8bef9SDimitry Andric     }
450e8d8bef9SDimitry Andric     ++ExpectedIndex;
4518bcb0991SDimitry Andric     writeUint8(OS, Table.ElemType);
4528bcb0991SDimitry Andric     writeLimits(Table.TableLimits, OS);
4538bcb0991SDimitry Andric   }
4548bcb0991SDimitry Andric }
4558bcb0991SDimitry Andric 
4568bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4578bcb0991SDimitry Andric                                      WasmYAML::MemorySection &Section) {
4588bcb0991SDimitry Andric   encodeULEB128(Section.Memories.size(), OS);
4598bcb0991SDimitry Andric   for (const WasmYAML::Limits &Mem : Section.Memories)
4608bcb0991SDimitry Andric     writeLimits(Mem, OS);
4618bcb0991SDimitry Andric }
4628bcb0991SDimitry Andric 
4638bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
464fe6060f1SDimitry Andric                                      WasmYAML::TagSection &Section) {
465*349cc55cSDimitry Andric   encodeULEB128(Section.TagTypes.size(), OS);
466*349cc55cSDimitry Andric   for (uint32_t TagType : Section.TagTypes) {
467*349cc55cSDimitry Andric     writeUint8(OS, 0); // Reserved 'attribute' field
468*349cc55cSDimitry Andric     encodeULEB128(TagType, OS);
4695ffd83dbSDimitry Andric   }
4705ffd83dbSDimitry Andric }
4715ffd83dbSDimitry Andric 
4725ffd83dbSDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4738bcb0991SDimitry Andric                                      WasmYAML::GlobalSection &Section) {
4748bcb0991SDimitry Andric   encodeULEB128(Section.Globals.size(), OS);
4758bcb0991SDimitry Andric   uint32_t ExpectedIndex = NumImportedGlobals;
4768bcb0991SDimitry Andric   for (auto &Global : Section.Globals) {
4778bcb0991SDimitry Andric     if (Global.Index != ExpectedIndex) {
4788bcb0991SDimitry Andric       reportError("unexpected global index: " + Twine(Global.Index));
4798bcb0991SDimitry Andric       return;
4808bcb0991SDimitry Andric     }
4818bcb0991SDimitry Andric     ++ExpectedIndex;
4828bcb0991SDimitry Andric     writeUint8(OS, Global.Type);
4838bcb0991SDimitry Andric     writeUint8(OS, Global.Mutable);
4848bcb0991SDimitry Andric     writeInitExpr(OS, Global.InitExpr);
4858bcb0991SDimitry Andric   }
4868bcb0991SDimitry Andric }
4878bcb0991SDimitry Andric 
4888bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4898bcb0991SDimitry Andric                                      WasmYAML::ElemSection &Section) {
4908bcb0991SDimitry Andric   encodeULEB128(Section.Segments.size(), OS);
4918bcb0991SDimitry Andric   for (auto &Segment : Section.Segments) {
492fe6060f1SDimitry Andric     encodeULEB128(Segment.Flags, OS);
493fe6060f1SDimitry Andric     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
494fe6060f1SDimitry Andric       encodeULEB128(Segment.TableNumber, OS);
495fe6060f1SDimitry Andric 
4968bcb0991SDimitry Andric     writeInitExpr(OS, Segment.Offset);
4978bcb0991SDimitry Andric 
498fe6060f1SDimitry Andric     if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
499fe6060f1SDimitry Andric       // We only support active function table initializers, for which the elem
500fe6060f1SDimitry Andric       // kind is specified to be written as 0x00 and interpreted to mean
501fe6060f1SDimitry Andric       // "funcref".
502fe6060f1SDimitry Andric       if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {
503fe6060f1SDimitry Andric         reportError("unexpected elemkind: " + Twine(Segment.ElemKind));
504fe6060f1SDimitry Andric         return;
505fe6060f1SDimitry Andric       }
506fe6060f1SDimitry Andric       const uint8_t ElemKind = 0;
507fe6060f1SDimitry Andric       writeUint8(OS, ElemKind);
508fe6060f1SDimitry Andric     }
509fe6060f1SDimitry Andric 
5108bcb0991SDimitry Andric     encodeULEB128(Segment.Functions.size(), OS);
5118bcb0991SDimitry Andric     for (auto &Function : Segment.Functions)
5128bcb0991SDimitry Andric       encodeULEB128(Function, OS);
5138bcb0991SDimitry Andric   }
5148bcb0991SDimitry Andric }
5158bcb0991SDimitry Andric 
5168bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
5178bcb0991SDimitry Andric                                     WasmYAML::CodeSection &Section) {
5188bcb0991SDimitry Andric   encodeULEB128(Section.Functions.size(), OS);
5198bcb0991SDimitry Andric   uint32_t ExpectedIndex = NumImportedFunctions;
5208bcb0991SDimitry Andric   for (auto &Func : Section.Functions) {
5218bcb0991SDimitry Andric     std::string OutString;
5228bcb0991SDimitry Andric     raw_string_ostream StringStream(OutString);
5238bcb0991SDimitry Andric     if (Func.Index != ExpectedIndex) {
5248bcb0991SDimitry Andric       reportError("unexpected function index: " + Twine(Func.Index));
5258bcb0991SDimitry Andric       return;
5268bcb0991SDimitry Andric     }
5278bcb0991SDimitry Andric     ++ExpectedIndex;
5288bcb0991SDimitry Andric 
5298bcb0991SDimitry Andric     encodeULEB128(Func.Locals.size(), StringStream);
5308bcb0991SDimitry Andric     for (auto &LocalDecl : Func.Locals) {
5318bcb0991SDimitry Andric       encodeULEB128(LocalDecl.Count, StringStream);
5328bcb0991SDimitry Andric       writeUint8(StringStream, LocalDecl.Type);
5338bcb0991SDimitry Andric     }
5348bcb0991SDimitry Andric 
5358bcb0991SDimitry Andric     Func.Body.writeAsBinary(StringStream);
5368bcb0991SDimitry Andric 
5378bcb0991SDimitry Andric     // Write the section size followed by the content
5388bcb0991SDimitry Andric     StringStream.flush();
5398bcb0991SDimitry Andric     encodeULEB128(OutString.size(), OS);
5408bcb0991SDimitry Andric     OS << OutString;
5418bcb0991SDimitry Andric   }
5428bcb0991SDimitry Andric }
5438bcb0991SDimitry Andric 
5448bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
5458bcb0991SDimitry Andric                                      WasmYAML::DataSection &Section) {
5468bcb0991SDimitry Andric   encodeULEB128(Section.Segments.size(), OS);
5478bcb0991SDimitry Andric   for (auto &Segment : Section.Segments) {
5488bcb0991SDimitry Andric     encodeULEB128(Segment.InitFlags, OS);
549e8d8bef9SDimitry Andric     if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
5508bcb0991SDimitry Andric       encodeULEB128(Segment.MemoryIndex, OS);
551e8d8bef9SDimitry Andric     if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)
5528bcb0991SDimitry Andric       writeInitExpr(OS, Segment.Offset);
5538bcb0991SDimitry Andric     encodeULEB128(Segment.Content.binary_size(), OS);
5548bcb0991SDimitry Andric     Segment.Content.writeAsBinary(OS);
5558bcb0991SDimitry Andric   }
5568bcb0991SDimitry Andric }
5578bcb0991SDimitry Andric 
5588bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
5598bcb0991SDimitry Andric                                      WasmYAML::DataCountSection &Section) {
5608bcb0991SDimitry Andric   encodeULEB128(Section.Count, OS);
5618bcb0991SDimitry Andric }
5628bcb0991SDimitry Andric 
5638bcb0991SDimitry Andric void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
5648bcb0991SDimitry Andric                                   uint32_t SectionIndex) {
5658bcb0991SDimitry Andric   switch (Sec.Type) {
5668bcb0991SDimitry Andric   case wasm::WASM_SEC_CODE:
5678bcb0991SDimitry Andric     writeStringRef("reloc.CODE", OS);
5688bcb0991SDimitry Andric     break;
5698bcb0991SDimitry Andric   case wasm::WASM_SEC_DATA:
5708bcb0991SDimitry Andric     writeStringRef("reloc.DATA", OS);
5718bcb0991SDimitry Andric     break;
5728bcb0991SDimitry Andric   case wasm::WASM_SEC_CUSTOM: {
5738bcb0991SDimitry Andric     auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
5748bcb0991SDimitry Andric     writeStringRef(("reloc." + CustomSection->Name).str(), OS);
5758bcb0991SDimitry Andric     break;
5768bcb0991SDimitry Andric   }
5778bcb0991SDimitry Andric   default:
5788bcb0991SDimitry Andric     llvm_unreachable("not yet implemented");
5798bcb0991SDimitry Andric   }
5808bcb0991SDimitry Andric 
5818bcb0991SDimitry Andric   encodeULEB128(SectionIndex, OS);
5828bcb0991SDimitry Andric   encodeULEB128(Sec.Relocations.size(), OS);
5838bcb0991SDimitry Andric 
5848bcb0991SDimitry Andric   for (auto Reloc : Sec.Relocations) {
5858bcb0991SDimitry Andric     writeUint8(OS, Reloc.Type);
5868bcb0991SDimitry Andric     encodeULEB128(Reloc.Offset, OS);
5878bcb0991SDimitry Andric     encodeULEB128(Reloc.Index, OS);
5888bcb0991SDimitry Andric     switch (Reloc.Type) {
5898bcb0991SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_LEB:
5905ffd83dbSDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_LEB64:
5918bcb0991SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_SLEB:
5925ffd83dbSDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_SLEB64:
5938bcb0991SDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_I32:
5945ffd83dbSDimitry Andric     case wasm::R_WASM_MEMORY_ADDR_I64:
5958bcb0991SDimitry Andric     case wasm::R_WASM_FUNCTION_OFFSET_I32:
596e8d8bef9SDimitry Andric     case wasm::R_WASM_FUNCTION_OFFSET_I64:
5978bcb0991SDimitry Andric     case wasm::R_WASM_SECTION_OFFSET_I32:
598fe6060f1SDimitry Andric       encodeSLEB128(Reloc.Addend, OS);
599fe6060f1SDimitry Andric       break;
6008bcb0991SDimitry Andric     }
6018bcb0991SDimitry Andric   }
6028bcb0991SDimitry Andric }
6038bcb0991SDimitry Andric 
6048bcb0991SDimitry Andric bool WasmWriter::writeWasm(raw_ostream &OS) {
6058bcb0991SDimitry Andric   // Write headers
6068bcb0991SDimitry Andric   OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
6078bcb0991SDimitry Andric   writeUint32(OS, Obj.Header.Version);
6088bcb0991SDimitry Andric 
6098bcb0991SDimitry Andric   // Write each section
6108bcb0991SDimitry Andric   llvm::object::WasmSectionOrderChecker Checker;
6118bcb0991SDimitry Andric   for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
6128bcb0991SDimitry Andric     StringRef SecName = "";
6138bcb0991SDimitry Andric     if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
6148bcb0991SDimitry Andric       SecName = S->Name;
6158bcb0991SDimitry Andric     if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
6168bcb0991SDimitry Andric       reportError("out of order section type: " + Twine(Sec->Type));
6178bcb0991SDimitry Andric       return false;
6188bcb0991SDimitry Andric     }
6198bcb0991SDimitry Andric     encodeULEB128(Sec->Type, OS);
6208bcb0991SDimitry Andric     std::string OutString;
6218bcb0991SDimitry Andric     raw_string_ostream StringStream(OutString);
6228bcb0991SDimitry Andric     if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
6238bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6248bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
6258bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6268bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
6278bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6288bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
6298bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6308bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
6318bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6328bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
6338bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
634fe6060f1SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))
6358bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6365ffd83dbSDimitry Andric     else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
6375ffd83dbSDimitry Andric       writeSectionContent(StringStream, *S);
6388bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
6398bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6408bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
6418bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6428bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
6438bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6448bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
6458bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6468bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
6478bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6488bcb0991SDimitry Andric     else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
6498bcb0991SDimitry Andric       writeSectionContent(StringStream, *S);
6508bcb0991SDimitry Andric     else
6518bcb0991SDimitry Andric       reportError("unknown section type: " + Twine(Sec->Type));
6528bcb0991SDimitry Andric 
6538bcb0991SDimitry Andric     if (HasError)
6548bcb0991SDimitry Andric       return false;
6558bcb0991SDimitry Andric 
6568bcb0991SDimitry Andric     StringStream.flush();
6578bcb0991SDimitry Andric 
6588bcb0991SDimitry Andric     // Write the section size followed by the content
6598bcb0991SDimitry Andric     encodeULEB128(OutString.size(), OS);
6608bcb0991SDimitry Andric     OS << OutString;
6618bcb0991SDimitry Andric   }
6628bcb0991SDimitry Andric 
6638bcb0991SDimitry Andric   // write reloc sections for any section that have relocations
6648bcb0991SDimitry Andric   uint32_t SectionIndex = 0;
6658bcb0991SDimitry Andric   for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
6668bcb0991SDimitry Andric     if (Sec->Relocations.empty()) {
6678bcb0991SDimitry Andric       SectionIndex++;
6688bcb0991SDimitry Andric       continue;
6698bcb0991SDimitry Andric     }
6708bcb0991SDimitry Andric 
6718bcb0991SDimitry Andric     writeUint8(OS, wasm::WASM_SEC_CUSTOM);
6728bcb0991SDimitry Andric     std::string OutString;
6738bcb0991SDimitry Andric     raw_string_ostream StringStream(OutString);
6748bcb0991SDimitry Andric     writeRelocSection(StringStream, *Sec, SectionIndex++);
6758bcb0991SDimitry Andric     StringStream.flush();
6768bcb0991SDimitry Andric 
6778bcb0991SDimitry Andric     encodeULEB128(OutString.size(), OS);
6788bcb0991SDimitry Andric     OS << OutString;
6798bcb0991SDimitry Andric   }
6808bcb0991SDimitry Andric 
6818bcb0991SDimitry Andric   return true;
6828bcb0991SDimitry Andric }
6838bcb0991SDimitry Andric 
6848bcb0991SDimitry Andric namespace llvm {
6858bcb0991SDimitry Andric namespace yaml {
6868bcb0991SDimitry Andric 
6878bcb0991SDimitry Andric bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
6888bcb0991SDimitry Andric   WasmWriter Writer(Doc, EH);
6898bcb0991SDimitry Andric   return Writer.writeWasm(Out);
6908bcb0991SDimitry Andric }
6918bcb0991SDimitry Andric 
6928bcb0991SDimitry Andric } // namespace yaml
6938bcb0991SDimitry Andric } // namespace llvm
694