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:
WasmWriter(WasmYAML::Object & Obj,yaml::ErrorHandler EH)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
3681ad6265SDimitry Andric void writeInitExpr(raw_ostream &OS, const WasmYAML::InitExpr &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:
SubSectionWriter(raw_ostream & OS)778bcb0991SDimitry Andric SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
788bcb0991SDimitry Andric
done()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
getStream()868bcb0991SDimitry Andric raw_ostream &getStream() { return StringStream; }
878bcb0991SDimitry Andric };
888bcb0991SDimitry Andric
898bcb0991SDimitry Andric } // end anonymous namespace
908bcb0991SDimitry Andric
writeUint64(raw_ostream & OS,uint64_t Value)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
writeUint32(raw_ostream & OS,uint32_t Value)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
writeUint8(raw_ostream & OS,uint8_t Value)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
writeStringRef(const StringRef & Str,raw_ostream & OS)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
writeLimits(const WasmYAML::Limits & Lim,raw_ostream & OS)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
reportError(const Twine & Msg)1268bcb0991SDimitry Andric void WasmWriter::reportError(const Twine &Msg) {
1278bcb0991SDimitry Andric ErrHandler(Msg);
1288bcb0991SDimitry Andric HasError = true;
1298bcb0991SDimitry Andric }
1308bcb0991SDimitry Andric
writeInitExpr(raw_ostream & OS,const WasmYAML::InitExpr & InitExpr)1318bcb0991SDimitry Andric void WasmWriter::writeInitExpr(raw_ostream &OS,
13281ad6265SDimitry Andric const WasmYAML::InitExpr &InitExpr) {
13381ad6265SDimitry Andric if (InitExpr.Extended) {
13481ad6265SDimitry Andric InitExpr.Body.writeAsBinary(OS);
13581ad6265SDimitry Andric } else {
13681ad6265SDimitry Andric writeUint8(OS, InitExpr.Inst.Opcode);
13781ad6265SDimitry Andric switch (InitExpr.Inst.Opcode) {
1388bcb0991SDimitry Andric case wasm::WASM_OPCODE_I32_CONST:
13981ad6265SDimitry Andric encodeSLEB128(InitExpr.Inst.Value.Int32, OS);
1408bcb0991SDimitry Andric break;
1418bcb0991SDimitry Andric case wasm::WASM_OPCODE_I64_CONST:
14281ad6265SDimitry Andric encodeSLEB128(InitExpr.Inst.Value.Int64, OS);
1438bcb0991SDimitry Andric break;
1448bcb0991SDimitry Andric case wasm::WASM_OPCODE_F32_CONST:
14581ad6265SDimitry Andric writeUint32(OS, InitExpr.Inst.Value.Float32);
1468bcb0991SDimitry Andric break;
1478bcb0991SDimitry Andric case wasm::WASM_OPCODE_F64_CONST:
14881ad6265SDimitry Andric writeUint64(OS, InitExpr.Inst.Value.Float64);
1498bcb0991SDimitry Andric break;
1508bcb0991SDimitry Andric case wasm::WASM_OPCODE_GLOBAL_GET:
15181ad6265SDimitry Andric encodeULEB128(InitExpr.Inst.Value.Global, OS);
1528bcb0991SDimitry Andric break;
1538bcb0991SDimitry Andric default:
15481ad6265SDimitry Andric reportError("unknown opcode in init_expr: " +
15581ad6265SDimitry Andric Twine(InitExpr.Inst.Opcode));
1568bcb0991SDimitry Andric return;
1578bcb0991SDimitry Andric }
1588bcb0991SDimitry Andric writeUint8(OS, wasm::WASM_OPCODE_END);
1598bcb0991SDimitry Andric }
16081ad6265SDimitry Andric }
1618bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::DylinkSection & Section)1628bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
1638bcb0991SDimitry Andric WasmYAML::DylinkSection &Section) {
1648bcb0991SDimitry Andric writeStringRef(Section.Name, OS);
165349cc55cSDimitry Andric
166349cc55cSDimitry Andric writeUint8(OS, wasm::WASM_DYLINK_MEM_INFO);
167349cc55cSDimitry Andric SubSectionWriter SubSection(OS);
168349cc55cSDimitry Andric raw_ostream &SubOS = SubSection.getStream();
169349cc55cSDimitry Andric encodeULEB128(Section.MemorySize, SubOS);
170349cc55cSDimitry Andric encodeULEB128(Section.MemoryAlignment, SubOS);
171349cc55cSDimitry Andric encodeULEB128(Section.TableSize, SubOS);
172349cc55cSDimitry Andric encodeULEB128(Section.TableAlignment, SubOS);
173349cc55cSDimitry Andric SubSection.done();
174349cc55cSDimitry Andric
175349cc55cSDimitry Andric if (Section.Needed.size()) {
176349cc55cSDimitry Andric writeUint8(OS, wasm::WASM_DYLINK_NEEDED);
177349cc55cSDimitry Andric raw_ostream &SubOS = SubSection.getStream();
178349cc55cSDimitry Andric encodeULEB128(Section.Needed.size(), SubOS);
1798bcb0991SDimitry Andric for (StringRef Needed : Section.Needed)
180349cc55cSDimitry Andric writeStringRef(Needed, SubOS);
181349cc55cSDimitry Andric SubSection.done();
182349cc55cSDimitry Andric }
1838bcb0991SDimitry Andric }
1848bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::LinkingSection & Section)1858bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
1868bcb0991SDimitry Andric WasmYAML::LinkingSection &Section) {
1878bcb0991SDimitry Andric writeStringRef(Section.Name, OS);
1888bcb0991SDimitry Andric encodeULEB128(Section.Version, OS);
1898bcb0991SDimitry Andric
1908bcb0991SDimitry Andric SubSectionWriter SubSection(OS);
1918bcb0991SDimitry Andric
1928bcb0991SDimitry Andric // SYMBOL_TABLE subsection
1938bcb0991SDimitry Andric if (Section.SymbolTable.size()) {
1948bcb0991SDimitry Andric writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
1958bcb0991SDimitry Andric encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
19681ad6265SDimitry Andric for (auto Sym : llvm::enumerate(Section.SymbolTable)) {
19781ad6265SDimitry Andric const WasmYAML::SymbolInfo &Info = Sym.value();
19881ad6265SDimitry Andric assert(Info.Index == Sym.index());
1998bcb0991SDimitry Andric writeUint8(SubSection.getStream(), Info.Kind);
2008bcb0991SDimitry Andric encodeULEB128(Info.Flags, SubSection.getStream());
2018bcb0991SDimitry Andric switch (Info.Kind) {
2028bcb0991SDimitry Andric case wasm::WASM_SYMBOL_TYPE_FUNCTION:
2038bcb0991SDimitry Andric case wasm::WASM_SYMBOL_TYPE_GLOBAL:
204e8d8bef9SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TABLE:
205fe6060f1SDimitry Andric case wasm::WASM_SYMBOL_TYPE_TAG:
2068bcb0991SDimitry Andric encodeULEB128(Info.ElementIndex, SubSection.getStream());
2078bcb0991SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
2088bcb0991SDimitry Andric (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
2098bcb0991SDimitry Andric writeStringRef(Info.Name, SubSection.getStream());
2108bcb0991SDimitry Andric break;
2118bcb0991SDimitry Andric case wasm::WASM_SYMBOL_TYPE_DATA:
2128bcb0991SDimitry Andric writeStringRef(Info.Name, SubSection.getStream());
2138bcb0991SDimitry Andric if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
2148bcb0991SDimitry Andric encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
2158bcb0991SDimitry Andric encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
2168bcb0991SDimitry Andric encodeULEB128(Info.DataRef.Size, SubSection.getStream());
2178bcb0991SDimitry Andric }
2188bcb0991SDimitry Andric break;
2198bcb0991SDimitry Andric case wasm::WASM_SYMBOL_TYPE_SECTION:
2208bcb0991SDimitry Andric encodeULEB128(Info.ElementIndex, SubSection.getStream());
2218bcb0991SDimitry Andric break;
2228bcb0991SDimitry Andric default:
2238bcb0991SDimitry Andric llvm_unreachable("unexpected kind");
2248bcb0991SDimitry Andric }
2258bcb0991SDimitry Andric }
2268bcb0991SDimitry Andric
2278bcb0991SDimitry Andric SubSection.done();
2288bcb0991SDimitry Andric }
2298bcb0991SDimitry Andric
2308bcb0991SDimitry Andric // SEGMENT_NAMES subsection
2318bcb0991SDimitry Andric if (Section.SegmentInfos.size()) {
2328bcb0991SDimitry Andric writeUint8(OS, wasm::WASM_SEGMENT_INFO);
2338bcb0991SDimitry Andric encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
2348bcb0991SDimitry Andric for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
2358bcb0991SDimitry Andric writeStringRef(SegmentInfo.Name, SubSection.getStream());
2368bcb0991SDimitry Andric encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
2378bcb0991SDimitry Andric encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
2388bcb0991SDimitry Andric }
2398bcb0991SDimitry Andric SubSection.done();
2408bcb0991SDimitry Andric }
2418bcb0991SDimitry Andric
2428bcb0991SDimitry Andric // INIT_FUNCS subsection
2438bcb0991SDimitry Andric if (Section.InitFunctions.size()) {
2448bcb0991SDimitry Andric writeUint8(OS, wasm::WASM_INIT_FUNCS);
2458bcb0991SDimitry Andric encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
2468bcb0991SDimitry Andric for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
2478bcb0991SDimitry Andric encodeULEB128(Func.Priority, SubSection.getStream());
2488bcb0991SDimitry Andric encodeULEB128(Func.Symbol, SubSection.getStream());
2498bcb0991SDimitry Andric }
2508bcb0991SDimitry Andric SubSection.done();
2518bcb0991SDimitry Andric }
2528bcb0991SDimitry Andric
2538bcb0991SDimitry Andric // COMDAT_INFO subsection
2548bcb0991SDimitry Andric if (Section.Comdats.size()) {
2558bcb0991SDimitry Andric writeUint8(OS, wasm::WASM_COMDAT_INFO);
2568bcb0991SDimitry Andric encodeULEB128(Section.Comdats.size(), SubSection.getStream());
2578bcb0991SDimitry Andric for (const auto &C : Section.Comdats) {
2588bcb0991SDimitry Andric writeStringRef(C.Name, SubSection.getStream());
2598bcb0991SDimitry Andric encodeULEB128(0, SubSection.getStream()); // flags for future use
2608bcb0991SDimitry Andric encodeULEB128(C.Entries.size(), SubSection.getStream());
2618bcb0991SDimitry Andric for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
2628bcb0991SDimitry Andric writeUint8(SubSection.getStream(), Entry.Kind);
2638bcb0991SDimitry Andric encodeULEB128(Entry.Index, SubSection.getStream());
2648bcb0991SDimitry Andric }
2658bcb0991SDimitry Andric }
2668bcb0991SDimitry Andric SubSection.done();
2678bcb0991SDimitry Andric }
2688bcb0991SDimitry Andric }
2698bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::NameSection & Section)2708bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
2718bcb0991SDimitry Andric WasmYAML::NameSection &Section) {
2728bcb0991SDimitry Andric writeStringRef(Section.Name, OS);
2738bcb0991SDimitry Andric if (Section.FunctionNames.size()) {
2748bcb0991SDimitry Andric writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
2758bcb0991SDimitry Andric
2768bcb0991SDimitry Andric SubSectionWriter SubSection(OS);
2778bcb0991SDimitry Andric
2788bcb0991SDimitry Andric encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
2798bcb0991SDimitry Andric for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
2808bcb0991SDimitry Andric encodeULEB128(NameEntry.Index, SubSection.getStream());
2818bcb0991SDimitry Andric writeStringRef(NameEntry.Name, SubSection.getStream());
2828bcb0991SDimitry Andric }
2838bcb0991SDimitry Andric
2848bcb0991SDimitry Andric SubSection.done();
2858bcb0991SDimitry Andric }
286e8d8bef9SDimitry Andric if (Section.GlobalNames.size()) {
287e8d8bef9SDimitry Andric writeUint8(OS, wasm::WASM_NAMES_GLOBAL);
288e8d8bef9SDimitry Andric
289e8d8bef9SDimitry Andric SubSectionWriter SubSection(OS);
290e8d8bef9SDimitry Andric
291e8d8bef9SDimitry Andric encodeULEB128(Section.GlobalNames.size(), SubSection.getStream());
292e8d8bef9SDimitry Andric for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {
293e8d8bef9SDimitry Andric encodeULEB128(NameEntry.Index, SubSection.getStream());
294e8d8bef9SDimitry Andric writeStringRef(NameEntry.Name, SubSection.getStream());
295e8d8bef9SDimitry Andric }
296e8d8bef9SDimitry Andric
297e8d8bef9SDimitry Andric SubSection.done();
298e8d8bef9SDimitry Andric }
299e8d8bef9SDimitry Andric if (Section.DataSegmentNames.size()) {
300e8d8bef9SDimitry Andric writeUint8(OS, wasm::WASM_NAMES_DATA_SEGMENT);
301e8d8bef9SDimitry Andric
302e8d8bef9SDimitry Andric SubSectionWriter SubSection(OS);
303e8d8bef9SDimitry Andric
304e8d8bef9SDimitry Andric encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());
305e8d8bef9SDimitry Andric for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {
306e8d8bef9SDimitry Andric encodeULEB128(NameEntry.Index, SubSection.getStream());
307e8d8bef9SDimitry Andric writeStringRef(NameEntry.Name, SubSection.getStream());
308e8d8bef9SDimitry Andric }
309e8d8bef9SDimitry Andric
310e8d8bef9SDimitry Andric SubSection.done();
311e8d8bef9SDimitry Andric }
3128bcb0991SDimitry Andric }
3138bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::ProducersSection & Section)3148bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3158bcb0991SDimitry Andric WasmYAML::ProducersSection &Section) {
3168bcb0991SDimitry Andric writeStringRef(Section.Name, OS);
3178bcb0991SDimitry Andric int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
3188bcb0991SDimitry Andric int(!Section.SDKs.empty());
3198bcb0991SDimitry Andric if (Fields == 0)
3208bcb0991SDimitry Andric return;
3218bcb0991SDimitry Andric encodeULEB128(Fields, OS);
3228bcb0991SDimitry Andric for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
3238bcb0991SDimitry Andric std::make_pair(StringRef("processed-by"), &Section.Tools),
3248bcb0991SDimitry Andric std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
3258bcb0991SDimitry Andric if (Field.second->empty())
3268bcb0991SDimitry Andric continue;
3278bcb0991SDimitry Andric writeStringRef(Field.first, OS);
3288bcb0991SDimitry Andric encodeULEB128(Field.second->size(), OS);
3298bcb0991SDimitry Andric for (auto &Entry : *Field.second) {
3308bcb0991SDimitry Andric writeStringRef(Entry.Name, OS);
3318bcb0991SDimitry Andric writeStringRef(Entry.Version, OS);
3328bcb0991SDimitry Andric }
3338bcb0991SDimitry Andric }
3348bcb0991SDimitry Andric }
3358bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::TargetFeaturesSection & Section)3368bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3378bcb0991SDimitry Andric WasmYAML::TargetFeaturesSection &Section) {
3388bcb0991SDimitry Andric writeStringRef(Section.Name, OS);
3398bcb0991SDimitry Andric encodeULEB128(Section.Features.size(), OS);
3408bcb0991SDimitry Andric for (auto &E : Section.Features) {
3418bcb0991SDimitry Andric writeUint8(OS, E.Prefix);
3428bcb0991SDimitry Andric writeStringRef(E.Name, OS);
3438bcb0991SDimitry Andric }
3448bcb0991SDimitry Andric }
3458bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::CustomSection & Section)3468bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3478bcb0991SDimitry Andric WasmYAML::CustomSection &Section) {
3488bcb0991SDimitry Andric if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
3498bcb0991SDimitry Andric writeSectionContent(OS, *S);
3508bcb0991SDimitry Andric } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
3518bcb0991SDimitry Andric writeSectionContent(OS, *S);
3528bcb0991SDimitry Andric } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
3538bcb0991SDimitry Andric writeSectionContent(OS, *S);
3548bcb0991SDimitry Andric } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
3558bcb0991SDimitry Andric writeSectionContent(OS, *S);
3568bcb0991SDimitry Andric } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
3578bcb0991SDimitry Andric writeSectionContent(OS, *S);
3588bcb0991SDimitry Andric } else {
3598bcb0991SDimitry Andric writeStringRef(Section.Name, OS);
3608bcb0991SDimitry Andric Section.Payload.writeAsBinary(OS);
3618bcb0991SDimitry Andric }
3628bcb0991SDimitry Andric }
3638bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::TypeSection & Section)3648bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3658bcb0991SDimitry Andric WasmYAML::TypeSection &Section) {
3668bcb0991SDimitry Andric encodeULEB128(Section.Signatures.size(), OS);
3678bcb0991SDimitry Andric uint32_t ExpectedIndex = 0;
3688bcb0991SDimitry Andric for (const WasmYAML::Signature &Sig : Section.Signatures) {
3698bcb0991SDimitry Andric if (Sig.Index != ExpectedIndex) {
3708bcb0991SDimitry Andric reportError("unexpected type index: " + Twine(Sig.Index));
3718bcb0991SDimitry Andric return;
3728bcb0991SDimitry Andric }
3738bcb0991SDimitry Andric ++ExpectedIndex;
3748bcb0991SDimitry Andric writeUint8(OS, Sig.Form);
3758bcb0991SDimitry Andric encodeULEB128(Sig.ParamTypes.size(), OS);
3768bcb0991SDimitry Andric for (auto ParamType : Sig.ParamTypes)
3778bcb0991SDimitry Andric writeUint8(OS, ParamType);
3788bcb0991SDimitry Andric encodeULEB128(Sig.ReturnTypes.size(), OS);
3798bcb0991SDimitry Andric for (auto ReturnType : Sig.ReturnTypes)
3808bcb0991SDimitry Andric writeUint8(OS, ReturnType);
3818bcb0991SDimitry Andric }
3828bcb0991SDimitry Andric }
3838bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::ImportSection & Section)3848bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
3858bcb0991SDimitry Andric WasmYAML::ImportSection &Section) {
3868bcb0991SDimitry Andric encodeULEB128(Section.Imports.size(), OS);
3878bcb0991SDimitry Andric for (const WasmYAML::Import &Import : Section.Imports) {
3888bcb0991SDimitry Andric writeStringRef(Import.Module, OS);
3898bcb0991SDimitry Andric writeStringRef(Import.Field, OS);
3908bcb0991SDimitry Andric writeUint8(OS, Import.Kind);
3918bcb0991SDimitry Andric switch (Import.Kind) {
3928bcb0991SDimitry Andric case wasm::WASM_EXTERNAL_FUNCTION:
3938bcb0991SDimitry Andric encodeULEB128(Import.SigIndex, OS);
3948bcb0991SDimitry Andric NumImportedFunctions++;
3958bcb0991SDimitry Andric break;
3968bcb0991SDimitry Andric case wasm::WASM_EXTERNAL_GLOBAL:
3978bcb0991SDimitry Andric writeUint8(OS, Import.GlobalImport.Type);
3988bcb0991SDimitry Andric writeUint8(OS, Import.GlobalImport.Mutable);
3998bcb0991SDimitry Andric NumImportedGlobals++;
4008bcb0991SDimitry Andric break;
401fe6060f1SDimitry Andric case wasm::WASM_EXTERNAL_TAG:
402349cc55cSDimitry Andric writeUint8(OS, 0); // Reserved 'attribute' field
403349cc55cSDimitry Andric encodeULEB128(Import.SigIndex, OS);
404fe6060f1SDimitry Andric NumImportedTags++;
4058bcb0991SDimitry Andric break;
4068bcb0991SDimitry Andric case wasm::WASM_EXTERNAL_MEMORY:
4078bcb0991SDimitry Andric writeLimits(Import.Memory, OS);
4088bcb0991SDimitry Andric break;
4098bcb0991SDimitry Andric case wasm::WASM_EXTERNAL_TABLE:
4108bcb0991SDimitry Andric writeUint8(OS, Import.TableImport.ElemType);
4118bcb0991SDimitry Andric writeLimits(Import.TableImport.TableLimits, OS);
412e8d8bef9SDimitry Andric NumImportedTables++;
4138bcb0991SDimitry Andric break;
4148bcb0991SDimitry Andric default:
4158bcb0991SDimitry Andric reportError("unknown import type: " +Twine(Import.Kind));
4168bcb0991SDimitry Andric return;
4178bcb0991SDimitry Andric }
4188bcb0991SDimitry Andric }
4198bcb0991SDimitry Andric }
4208bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::FunctionSection & Section)4218bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4228bcb0991SDimitry Andric WasmYAML::FunctionSection &Section) {
4238bcb0991SDimitry Andric encodeULEB128(Section.FunctionTypes.size(), OS);
4248bcb0991SDimitry Andric for (uint32_t FuncType : Section.FunctionTypes)
4258bcb0991SDimitry Andric encodeULEB128(FuncType, OS);
4268bcb0991SDimitry Andric }
4278bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::ExportSection & Section)4288bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4298bcb0991SDimitry Andric WasmYAML::ExportSection &Section) {
4308bcb0991SDimitry Andric encodeULEB128(Section.Exports.size(), OS);
4318bcb0991SDimitry Andric for (const WasmYAML::Export &Export : Section.Exports) {
4328bcb0991SDimitry Andric writeStringRef(Export.Name, OS);
4338bcb0991SDimitry Andric writeUint8(OS, Export.Kind);
4348bcb0991SDimitry Andric encodeULEB128(Export.Index, OS);
4358bcb0991SDimitry Andric }
4368bcb0991SDimitry Andric }
4378bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::StartSection & Section)4388bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4398bcb0991SDimitry Andric WasmYAML::StartSection &Section) {
4408bcb0991SDimitry Andric encodeULEB128(Section.StartFunction, OS);
4418bcb0991SDimitry Andric }
4428bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::TableSection & Section)4438bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4448bcb0991SDimitry Andric WasmYAML::TableSection &Section) {
4458bcb0991SDimitry Andric encodeULEB128(Section.Tables.size(), OS);
446e8d8bef9SDimitry Andric uint32_t ExpectedIndex = NumImportedTables;
4478bcb0991SDimitry Andric for (auto &Table : Section.Tables) {
448e8d8bef9SDimitry Andric if (Table.Index != ExpectedIndex) {
449e8d8bef9SDimitry Andric reportError("unexpected table index: " + Twine(Table.Index));
450e8d8bef9SDimitry Andric return;
451e8d8bef9SDimitry Andric }
452e8d8bef9SDimitry Andric ++ExpectedIndex;
4538bcb0991SDimitry Andric writeUint8(OS, Table.ElemType);
4548bcb0991SDimitry Andric writeLimits(Table.TableLimits, OS);
4558bcb0991SDimitry Andric }
4568bcb0991SDimitry Andric }
4578bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::MemorySection & Section)4588bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4598bcb0991SDimitry Andric WasmYAML::MemorySection &Section) {
4608bcb0991SDimitry Andric encodeULEB128(Section.Memories.size(), OS);
4618bcb0991SDimitry Andric for (const WasmYAML::Limits &Mem : Section.Memories)
4628bcb0991SDimitry Andric writeLimits(Mem, OS);
4638bcb0991SDimitry Andric }
4648bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::TagSection & Section)4658bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
466fe6060f1SDimitry Andric WasmYAML::TagSection &Section) {
467349cc55cSDimitry Andric encodeULEB128(Section.TagTypes.size(), OS);
468349cc55cSDimitry Andric for (uint32_t TagType : Section.TagTypes) {
469349cc55cSDimitry Andric writeUint8(OS, 0); // Reserved 'attribute' field
470349cc55cSDimitry Andric encodeULEB128(TagType, OS);
4715ffd83dbSDimitry Andric }
4725ffd83dbSDimitry Andric }
4735ffd83dbSDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::GlobalSection & Section)4745ffd83dbSDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4758bcb0991SDimitry Andric WasmYAML::GlobalSection &Section) {
4768bcb0991SDimitry Andric encodeULEB128(Section.Globals.size(), OS);
4778bcb0991SDimitry Andric uint32_t ExpectedIndex = NumImportedGlobals;
4788bcb0991SDimitry Andric for (auto &Global : Section.Globals) {
4798bcb0991SDimitry Andric if (Global.Index != ExpectedIndex) {
4808bcb0991SDimitry Andric reportError("unexpected global index: " + Twine(Global.Index));
4818bcb0991SDimitry Andric return;
4828bcb0991SDimitry Andric }
4838bcb0991SDimitry Andric ++ExpectedIndex;
4848bcb0991SDimitry Andric writeUint8(OS, Global.Type);
4858bcb0991SDimitry Andric writeUint8(OS, Global.Mutable);
48681ad6265SDimitry Andric writeInitExpr(OS, Global.Init);
4878bcb0991SDimitry Andric }
4888bcb0991SDimitry Andric }
4898bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::ElemSection & Section)4908bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
4918bcb0991SDimitry Andric WasmYAML::ElemSection &Section) {
4928bcb0991SDimitry Andric encodeULEB128(Section.Segments.size(), OS);
4938bcb0991SDimitry Andric for (auto &Segment : Section.Segments) {
494fe6060f1SDimitry Andric encodeULEB128(Segment.Flags, OS);
495fe6060f1SDimitry Andric if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
496fe6060f1SDimitry Andric encodeULEB128(Segment.TableNumber, OS);
497fe6060f1SDimitry Andric
4988bcb0991SDimitry Andric writeInitExpr(OS, Segment.Offset);
4998bcb0991SDimitry Andric
500fe6060f1SDimitry Andric if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
501fe6060f1SDimitry Andric // We only support active function table initializers, for which the elem
502fe6060f1SDimitry Andric // kind is specified to be written as 0x00 and interpreted to mean
503fe6060f1SDimitry Andric // "funcref".
504fe6060f1SDimitry Andric if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {
505fe6060f1SDimitry Andric reportError("unexpected elemkind: " + Twine(Segment.ElemKind));
506fe6060f1SDimitry Andric return;
507fe6060f1SDimitry Andric }
508fe6060f1SDimitry Andric const uint8_t ElemKind = 0;
509fe6060f1SDimitry Andric writeUint8(OS, ElemKind);
510fe6060f1SDimitry Andric }
511fe6060f1SDimitry Andric
5128bcb0991SDimitry Andric encodeULEB128(Segment.Functions.size(), OS);
5138bcb0991SDimitry Andric for (auto &Function : Segment.Functions)
5148bcb0991SDimitry Andric encodeULEB128(Function, OS);
5158bcb0991SDimitry Andric }
5168bcb0991SDimitry Andric }
5178bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::CodeSection & Section)5188bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
5198bcb0991SDimitry Andric WasmYAML::CodeSection &Section) {
5208bcb0991SDimitry Andric encodeULEB128(Section.Functions.size(), OS);
5218bcb0991SDimitry Andric uint32_t ExpectedIndex = NumImportedFunctions;
5228bcb0991SDimitry Andric for (auto &Func : Section.Functions) {
5238bcb0991SDimitry Andric std::string OutString;
5248bcb0991SDimitry Andric raw_string_ostream StringStream(OutString);
5258bcb0991SDimitry Andric if (Func.Index != ExpectedIndex) {
5268bcb0991SDimitry Andric reportError("unexpected function index: " + Twine(Func.Index));
5278bcb0991SDimitry Andric return;
5288bcb0991SDimitry Andric }
5298bcb0991SDimitry Andric ++ExpectedIndex;
5308bcb0991SDimitry Andric
5318bcb0991SDimitry Andric encodeULEB128(Func.Locals.size(), StringStream);
5328bcb0991SDimitry Andric for (auto &LocalDecl : Func.Locals) {
5338bcb0991SDimitry Andric encodeULEB128(LocalDecl.Count, StringStream);
5348bcb0991SDimitry Andric writeUint8(StringStream, LocalDecl.Type);
5358bcb0991SDimitry Andric }
5368bcb0991SDimitry Andric
5378bcb0991SDimitry Andric Func.Body.writeAsBinary(StringStream);
5388bcb0991SDimitry Andric
5398bcb0991SDimitry Andric // Write the section size followed by the content
5408bcb0991SDimitry Andric StringStream.flush();
5418bcb0991SDimitry Andric encodeULEB128(OutString.size(), OS);
5428bcb0991SDimitry Andric OS << OutString;
5438bcb0991SDimitry Andric }
5448bcb0991SDimitry Andric }
5458bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::DataSection & Section)5468bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
5478bcb0991SDimitry Andric WasmYAML::DataSection &Section) {
5488bcb0991SDimitry Andric encodeULEB128(Section.Segments.size(), OS);
5498bcb0991SDimitry Andric for (auto &Segment : Section.Segments) {
5508bcb0991SDimitry Andric encodeULEB128(Segment.InitFlags, OS);
551e8d8bef9SDimitry Andric if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
5528bcb0991SDimitry Andric encodeULEB128(Segment.MemoryIndex, OS);
553e8d8bef9SDimitry Andric if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)
5548bcb0991SDimitry Andric writeInitExpr(OS, Segment.Offset);
5558bcb0991SDimitry Andric encodeULEB128(Segment.Content.binary_size(), OS);
5568bcb0991SDimitry Andric Segment.Content.writeAsBinary(OS);
5578bcb0991SDimitry Andric }
5588bcb0991SDimitry Andric }
5598bcb0991SDimitry Andric
writeSectionContent(raw_ostream & OS,WasmYAML::DataCountSection & Section)5608bcb0991SDimitry Andric void WasmWriter::writeSectionContent(raw_ostream &OS,
5618bcb0991SDimitry Andric WasmYAML::DataCountSection &Section) {
5628bcb0991SDimitry Andric encodeULEB128(Section.Count, OS);
5638bcb0991SDimitry Andric }
5648bcb0991SDimitry Andric
writeRelocSection(raw_ostream & OS,WasmYAML::Section & Sec,uint32_t SectionIndex)5658bcb0991SDimitry Andric void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
5668bcb0991SDimitry Andric uint32_t SectionIndex) {
5678bcb0991SDimitry Andric switch (Sec.Type) {
5688bcb0991SDimitry Andric case wasm::WASM_SEC_CODE:
5698bcb0991SDimitry Andric writeStringRef("reloc.CODE", OS);
5708bcb0991SDimitry Andric break;
5718bcb0991SDimitry Andric case wasm::WASM_SEC_DATA:
5728bcb0991SDimitry Andric writeStringRef("reloc.DATA", OS);
5738bcb0991SDimitry Andric break;
5748bcb0991SDimitry Andric case wasm::WASM_SEC_CUSTOM: {
5758bcb0991SDimitry Andric auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
5768bcb0991SDimitry Andric writeStringRef(("reloc." + CustomSection->Name).str(), OS);
5778bcb0991SDimitry Andric break;
5788bcb0991SDimitry Andric }
5798bcb0991SDimitry Andric default:
5808bcb0991SDimitry Andric llvm_unreachable("not yet implemented");
5818bcb0991SDimitry Andric }
5828bcb0991SDimitry Andric
5838bcb0991SDimitry Andric encodeULEB128(SectionIndex, OS);
5848bcb0991SDimitry Andric encodeULEB128(Sec.Relocations.size(), OS);
5858bcb0991SDimitry Andric
5868bcb0991SDimitry Andric for (auto Reloc : Sec.Relocations) {
5878bcb0991SDimitry Andric writeUint8(OS, Reloc.Type);
5888bcb0991SDimitry Andric encodeULEB128(Reloc.Offset, OS);
5898bcb0991SDimitry Andric encodeULEB128(Reloc.Index, OS);
5901fd87a68SDimitry Andric if (wasm::relocTypeHasAddend(Reloc.Type))
591fe6060f1SDimitry Andric encodeSLEB128(Reloc.Addend, OS);
5928bcb0991SDimitry Andric }
5938bcb0991SDimitry Andric }
5948bcb0991SDimitry Andric
writeWasm(raw_ostream & OS)5958bcb0991SDimitry Andric bool WasmWriter::writeWasm(raw_ostream &OS) {
5968bcb0991SDimitry Andric // Write headers
5978bcb0991SDimitry Andric OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
5988bcb0991SDimitry Andric writeUint32(OS, Obj.Header.Version);
5998bcb0991SDimitry Andric
6008bcb0991SDimitry Andric // Write each section
6018bcb0991SDimitry Andric llvm::object::WasmSectionOrderChecker Checker;
6028bcb0991SDimitry Andric for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
6038bcb0991SDimitry Andric StringRef SecName = "";
6048bcb0991SDimitry Andric if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
6058bcb0991SDimitry Andric SecName = S->Name;
6068bcb0991SDimitry Andric if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
6078bcb0991SDimitry Andric reportError("out of order section type: " + Twine(Sec->Type));
6088bcb0991SDimitry Andric return false;
6098bcb0991SDimitry Andric }
6108bcb0991SDimitry Andric encodeULEB128(Sec->Type, OS);
6118bcb0991SDimitry Andric std::string OutString;
6128bcb0991SDimitry Andric raw_string_ostream StringStream(OutString);
6138bcb0991SDimitry Andric if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
6148bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6158bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
6168bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6178bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
6188bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6198bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
6208bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6218bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
6228bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6238bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
6248bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
625fe6060f1SDimitry Andric else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))
6268bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6275ffd83dbSDimitry Andric else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
6285ffd83dbSDimitry Andric writeSectionContent(StringStream, *S);
6298bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
6308bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6318bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
6328bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6338bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
6348bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6358bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
6368bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6378bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
6388bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6398bcb0991SDimitry Andric else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
6408bcb0991SDimitry Andric writeSectionContent(StringStream, *S);
6418bcb0991SDimitry Andric else
6428bcb0991SDimitry Andric reportError("unknown section type: " + Twine(Sec->Type));
6438bcb0991SDimitry Andric
6448bcb0991SDimitry Andric if (HasError)
6458bcb0991SDimitry Andric return false;
6468bcb0991SDimitry Andric
6478bcb0991SDimitry Andric StringStream.flush();
6488bcb0991SDimitry Andric
649*8a4dda33SDimitry Andric unsigned HeaderSecSizeEncodingLen =
650*8a4dda33SDimitry Andric Sec->HeaderSecSizeEncodingLen ? *Sec->HeaderSecSizeEncodingLen : 5;
651*8a4dda33SDimitry Andric unsigned RequiredLen = getULEB128Size(OutString.size());
652*8a4dda33SDimitry Andric // Wasm spec does not allow LEBs larger than 5 bytes
653*8a4dda33SDimitry Andric assert(RequiredLen <= 5);
654*8a4dda33SDimitry Andric if (HeaderSecSizeEncodingLen < RequiredLen) {
655*8a4dda33SDimitry Andric reportError("section header length can't be encoded in a LEB of size " +
656*8a4dda33SDimitry Andric Twine(HeaderSecSizeEncodingLen));
657*8a4dda33SDimitry Andric return false;
658*8a4dda33SDimitry Andric }
6598bcb0991SDimitry Andric // Write the section size followed by the content
660*8a4dda33SDimitry Andric encodeULEB128(OutString.size(), OS, HeaderSecSizeEncodingLen);
6618bcb0991SDimitry Andric OS << OutString;
6628bcb0991SDimitry Andric }
6638bcb0991SDimitry Andric
6648bcb0991SDimitry Andric // write reloc sections for any section that have relocations
6658bcb0991SDimitry Andric uint32_t SectionIndex = 0;
6668bcb0991SDimitry Andric for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
6678bcb0991SDimitry Andric if (Sec->Relocations.empty()) {
6688bcb0991SDimitry Andric SectionIndex++;
6698bcb0991SDimitry Andric continue;
6708bcb0991SDimitry Andric }
6718bcb0991SDimitry Andric
6728bcb0991SDimitry Andric writeUint8(OS, wasm::WASM_SEC_CUSTOM);
6738bcb0991SDimitry Andric std::string OutString;
6748bcb0991SDimitry Andric raw_string_ostream StringStream(OutString);
6758bcb0991SDimitry Andric writeRelocSection(StringStream, *Sec, SectionIndex++);
6768bcb0991SDimitry Andric StringStream.flush();
6778bcb0991SDimitry Andric
6788bcb0991SDimitry Andric encodeULEB128(OutString.size(), OS);
6798bcb0991SDimitry Andric OS << OutString;
6808bcb0991SDimitry Andric }
6818bcb0991SDimitry Andric
6828bcb0991SDimitry Andric return true;
6838bcb0991SDimitry Andric }
6848bcb0991SDimitry Andric
6858bcb0991SDimitry Andric namespace llvm {
6868bcb0991SDimitry Andric namespace yaml {
6878bcb0991SDimitry Andric
yaml2wasm(WasmYAML::Object & Doc,raw_ostream & Out,ErrorHandler EH)6888bcb0991SDimitry Andric bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
6898bcb0991SDimitry Andric WasmWriter Writer(Doc, EH);
6908bcb0991SDimitry Andric return Writer.writeWasm(Out);
6918bcb0991SDimitry Andric }
6928bcb0991SDimitry Andric
6938bcb0991SDimitry Andric } // namespace yaml
6948bcb0991SDimitry Andric } // namespace llvm
695