1c22d9666SAlex Brachet //===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
2c22d9666SAlex Brachet //
3c22d9666SAlex Brachet // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c22d9666SAlex Brachet // See https://llvm.org/LICENSE.txt for license information.
5c22d9666SAlex Brachet // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c22d9666SAlex Brachet //
7c22d9666SAlex Brachet //===----------------------------------------------------------------------===//
8c22d9666SAlex Brachet ///
9c22d9666SAlex Brachet /// \file
10c22d9666SAlex Brachet /// The Wasm component of yaml2obj.
11c22d9666SAlex Brachet ///
12c22d9666SAlex Brachet //===----------------------------------------------------------------------===//
13c22d9666SAlex Brachet //
14c22d9666SAlex Brachet
15c22d9666SAlex Brachet #include "llvm/Object/Wasm.h"
16c22d9666SAlex Brachet #include "llvm/ObjectYAML/ObjectYAML.h"
17c22d9666SAlex Brachet #include "llvm/ObjectYAML/yaml2obj.h"
18c22d9666SAlex Brachet #include "llvm/Support/Endian.h"
19c22d9666SAlex Brachet #include "llvm/Support/LEB128.h"
20c22d9666SAlex Brachet
21c22d9666SAlex Brachet using namespace llvm;
22c22d9666SAlex Brachet
23c22d9666SAlex Brachet namespace {
24c22d9666SAlex Brachet /// This parses a yaml stream that represents a Wasm object file.
25c22d9666SAlex Brachet /// See docs/yaml2obj for the yaml scheema.
26c22d9666SAlex Brachet class WasmWriter {
27c22d9666SAlex Brachet public:
WasmWriter(WasmYAML::Object & Obj,yaml::ErrorHandler EH)2885011027SGeorge Rimar WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)
2985011027SGeorge Rimar : Obj(Obj), ErrHandler(EH) {}
307da559f2SGeorge Rimar bool writeWasm(raw_ostream &OS);
31c22d9666SAlex Brachet
32c22d9666SAlex Brachet private:
3385011027SGeorge Rimar void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
34c22d9666SAlex Brachet uint32_t SectionIndex);
35c22d9666SAlex Brachet
369504ab32SSam Clegg void writeInitExpr(raw_ostream &OS, const WasmYAML::InitExpr &InitExpr);
3785011027SGeorge Rimar
3885011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
3985011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
4085011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
4185011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
4285011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
4385011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
441d891d44SHeejin Ahn void writeSectionContent(raw_ostream &OS, WasmYAML::TagSection &Section);
45f93426c5SHeejin Ahn void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
4685011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
4785011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
4885011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
4985011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
5085011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
5185011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
52c22d9666SAlex Brachet
53c22d9666SAlex Brachet // Custom section types
5485011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
5585011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
5685011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
5785011027SGeorge Rimar void writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
5885011027SGeorge Rimar void writeSectionContent(raw_ostream &OS,
59c22d9666SAlex Brachet WasmYAML::TargetFeaturesSection &Section);
60c22d9666SAlex Brachet WasmYAML::Object &Obj;
61c22d9666SAlex Brachet uint32_t NumImportedFunctions = 0;
62c22d9666SAlex Brachet uint32_t NumImportedGlobals = 0;
63388fb67bSPaulo Matos uint32_t NumImportedTables = 0;
641d891d44SHeejin Ahn uint32_t NumImportedTags = 0;
6585011027SGeorge Rimar
6685011027SGeorge Rimar bool HasError = false;
6785011027SGeorge Rimar yaml::ErrorHandler ErrHandler;
6885011027SGeorge Rimar void reportError(const Twine &Msg);
69c22d9666SAlex Brachet };
70c22d9666SAlex Brachet
71c22d9666SAlex Brachet class SubSectionWriter {
72c22d9666SAlex Brachet raw_ostream &OS;
73c22d9666SAlex Brachet std::string OutString;
74c22d9666SAlex Brachet raw_string_ostream StringStream;
75c22d9666SAlex Brachet
76c22d9666SAlex Brachet public:
SubSectionWriter(raw_ostream & OS)77c22d9666SAlex Brachet SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
78c22d9666SAlex Brachet
done()79c22d9666SAlex Brachet void done() {
80c22d9666SAlex Brachet StringStream.flush();
81c22d9666SAlex Brachet encodeULEB128(OutString.size(), OS);
82c22d9666SAlex Brachet OS << OutString;
83c22d9666SAlex Brachet OutString.clear();
84c22d9666SAlex Brachet }
85c22d9666SAlex Brachet
getStream()86c22d9666SAlex Brachet raw_ostream &getStream() { return StringStream; }
87c22d9666SAlex Brachet };
88c22d9666SAlex Brachet
89c22d9666SAlex Brachet } // end anonymous namespace
90c22d9666SAlex Brachet
writeUint64(raw_ostream & OS,uint64_t Value)91c22d9666SAlex Brachet static int writeUint64(raw_ostream &OS, uint64_t Value) {
92c22d9666SAlex Brachet char Data[sizeof(Value)];
93c22d9666SAlex Brachet support::endian::write64le(Data, Value);
94c22d9666SAlex Brachet OS.write(Data, sizeof(Data));
95c22d9666SAlex Brachet return 0;
96c22d9666SAlex Brachet }
97c22d9666SAlex Brachet
writeUint32(raw_ostream & OS,uint32_t Value)98c22d9666SAlex Brachet static int writeUint32(raw_ostream &OS, uint32_t Value) {
99c22d9666SAlex Brachet char Data[sizeof(Value)];
100c22d9666SAlex Brachet support::endian::write32le(Data, Value);
101c22d9666SAlex Brachet OS.write(Data, sizeof(Data));
102c22d9666SAlex Brachet return 0;
103c22d9666SAlex Brachet }
104c22d9666SAlex Brachet
writeUint8(raw_ostream & OS,uint8_t Value)105c22d9666SAlex Brachet static int writeUint8(raw_ostream &OS, uint8_t Value) {
106c22d9666SAlex Brachet char Data[sizeof(Value)];
107c22d9666SAlex Brachet memcpy(Data, &Value, sizeof(Data));
108c22d9666SAlex Brachet OS.write(Data, sizeof(Data));
109c22d9666SAlex Brachet return 0;
110c22d9666SAlex Brachet }
111c22d9666SAlex Brachet
writeStringRef(const StringRef & Str,raw_ostream & OS)112c22d9666SAlex Brachet static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
113c22d9666SAlex Brachet encodeULEB128(Str.size(), OS);
114c22d9666SAlex Brachet OS << Str;
115c22d9666SAlex Brachet return 0;
116c22d9666SAlex Brachet }
117c22d9666SAlex Brachet
writeLimits(const WasmYAML::Limits & Lim,raw_ostream & OS)118c22d9666SAlex Brachet static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
119c22d9666SAlex Brachet writeUint8(OS, Lim.Flags);
1209ac5620cSAndy Wingo encodeULEB128(Lim.Minimum, OS);
121c22d9666SAlex Brachet if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
122c22d9666SAlex Brachet encodeULEB128(Lim.Maximum, OS);
123c22d9666SAlex Brachet return 0;
124c22d9666SAlex Brachet }
125c22d9666SAlex Brachet
reportError(const Twine & Msg)12685011027SGeorge Rimar void WasmWriter::reportError(const Twine &Msg) {
12785011027SGeorge Rimar ErrHandler(Msg);
12885011027SGeorge Rimar HasError = true;
12985011027SGeorge Rimar }
13085011027SGeorge Rimar
writeInitExpr(raw_ostream & OS,const WasmYAML::InitExpr & InitExpr)13185011027SGeorge Rimar void WasmWriter::writeInitExpr(raw_ostream &OS,
1329504ab32SSam Clegg const WasmYAML::InitExpr &InitExpr) {
1339504ab32SSam Clegg if (InitExpr.Extended) {
1349504ab32SSam Clegg InitExpr.Body.writeAsBinary(OS);
1359504ab32SSam Clegg } else {
1369504ab32SSam Clegg writeUint8(OS, InitExpr.Inst.Opcode);
1379504ab32SSam Clegg switch (InitExpr.Inst.Opcode) {
138c22d9666SAlex Brachet case wasm::WASM_OPCODE_I32_CONST:
1399504ab32SSam Clegg encodeSLEB128(InitExpr.Inst.Value.Int32, OS);
140c22d9666SAlex Brachet break;
141c22d9666SAlex Brachet case wasm::WASM_OPCODE_I64_CONST:
1429504ab32SSam Clegg encodeSLEB128(InitExpr.Inst.Value.Int64, OS);
143c22d9666SAlex Brachet break;
144c22d9666SAlex Brachet case wasm::WASM_OPCODE_F32_CONST:
1459504ab32SSam Clegg writeUint32(OS, InitExpr.Inst.Value.Float32);
146c22d9666SAlex Brachet break;
147c22d9666SAlex Brachet case wasm::WASM_OPCODE_F64_CONST:
1489504ab32SSam Clegg writeUint64(OS, InitExpr.Inst.Value.Float64);
149c22d9666SAlex Brachet break;
150c22d9666SAlex Brachet case wasm::WASM_OPCODE_GLOBAL_GET:
1519504ab32SSam Clegg encodeULEB128(InitExpr.Inst.Value.Global, OS);
152c22d9666SAlex Brachet break;
153c22d9666SAlex Brachet default:
1549504ab32SSam Clegg reportError("unknown opcode in init_expr: " +
1559504ab32SSam Clegg Twine(InitExpr.Inst.Opcode));
15685011027SGeorge Rimar return;
157c22d9666SAlex Brachet }
158c22d9666SAlex Brachet writeUint8(OS, wasm::WASM_OPCODE_END);
159c22d9666SAlex Brachet }
1609504ab32SSam Clegg }
161c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::DylinkSection & Section)16285011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
163c22d9666SAlex Brachet WasmYAML::DylinkSection &Section) {
164c22d9666SAlex Brachet writeStringRef(Section.Name, OS);
165b78c85a4SSam Clegg
166b78c85a4SSam Clegg writeUint8(OS, wasm::WASM_DYLINK_MEM_INFO);
167b78c85a4SSam Clegg SubSectionWriter SubSection(OS);
168b78c85a4SSam Clegg raw_ostream &SubOS = SubSection.getStream();
169b78c85a4SSam Clegg encodeULEB128(Section.MemorySize, SubOS);
170b78c85a4SSam Clegg encodeULEB128(Section.MemoryAlignment, SubOS);
171b78c85a4SSam Clegg encodeULEB128(Section.TableSize, SubOS);
172b78c85a4SSam Clegg encodeULEB128(Section.TableAlignment, SubOS);
173b78c85a4SSam Clegg SubSection.done();
174b78c85a4SSam Clegg
175b78c85a4SSam Clegg if (Section.Needed.size()) {
176b78c85a4SSam Clegg writeUint8(OS, wasm::WASM_DYLINK_NEEDED);
177b78c85a4SSam Clegg raw_ostream &SubOS = SubSection.getStream();
178b78c85a4SSam Clegg encodeULEB128(Section.Needed.size(), SubOS);
17985011027SGeorge Rimar for (StringRef Needed : Section.Needed)
180b78c85a4SSam Clegg writeStringRef(Needed, SubOS);
181b78c85a4SSam Clegg SubSection.done();
182b78c85a4SSam Clegg }
183c22d9666SAlex Brachet }
184c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::LinkingSection & Section)18585011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
186c22d9666SAlex Brachet WasmYAML::LinkingSection &Section) {
187c22d9666SAlex Brachet writeStringRef(Section.Name, OS);
188c22d9666SAlex Brachet encodeULEB128(Section.Version, OS);
189c22d9666SAlex Brachet
190c22d9666SAlex Brachet SubSectionWriter SubSection(OS);
191c22d9666SAlex Brachet
192c22d9666SAlex Brachet // SYMBOL_TABLE subsection
193c22d9666SAlex Brachet if (Section.SymbolTable.size()) {
194c22d9666SAlex Brachet writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
195c22d9666SAlex Brachet encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
1967848bf16SSimon Pilgrim for (auto Sym : llvm::enumerate(Section.SymbolTable)) {
1977848bf16SSimon Pilgrim const WasmYAML::SymbolInfo &Info = Sym.value();
1987848bf16SSimon Pilgrim assert(Info.Index == Sym.index());
199c22d9666SAlex Brachet writeUint8(SubSection.getStream(), Info.Kind);
200c22d9666SAlex Brachet encodeULEB128(Info.Flags, SubSection.getStream());
201c22d9666SAlex Brachet switch (Info.Kind) {
202c22d9666SAlex Brachet case wasm::WASM_SYMBOL_TYPE_FUNCTION:
203c22d9666SAlex Brachet case wasm::WASM_SYMBOL_TYPE_GLOBAL:
204388fb67bSPaulo Matos case wasm::WASM_SYMBOL_TYPE_TABLE:
2051d891d44SHeejin Ahn case wasm::WASM_SYMBOL_TYPE_TAG:
206c22d9666SAlex Brachet encodeULEB128(Info.ElementIndex, SubSection.getStream());
207c22d9666SAlex Brachet if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
208c22d9666SAlex Brachet (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
209c22d9666SAlex Brachet writeStringRef(Info.Name, SubSection.getStream());
210c22d9666SAlex Brachet break;
211c22d9666SAlex Brachet case wasm::WASM_SYMBOL_TYPE_DATA:
212c22d9666SAlex Brachet writeStringRef(Info.Name, SubSection.getStream());
213c22d9666SAlex Brachet if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
214c22d9666SAlex Brachet encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
215c22d9666SAlex Brachet encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
216c22d9666SAlex Brachet encodeULEB128(Info.DataRef.Size, SubSection.getStream());
217c22d9666SAlex Brachet }
218c22d9666SAlex Brachet break;
219c22d9666SAlex Brachet case wasm::WASM_SYMBOL_TYPE_SECTION:
220c22d9666SAlex Brachet encodeULEB128(Info.ElementIndex, SubSection.getStream());
221c22d9666SAlex Brachet break;
222c22d9666SAlex Brachet default:
223c22d9666SAlex Brachet llvm_unreachable("unexpected kind");
224c22d9666SAlex Brachet }
225c22d9666SAlex Brachet }
226c22d9666SAlex Brachet
227c22d9666SAlex Brachet SubSection.done();
228c22d9666SAlex Brachet }
229c22d9666SAlex Brachet
230c22d9666SAlex Brachet // SEGMENT_NAMES subsection
231c22d9666SAlex Brachet if (Section.SegmentInfos.size()) {
232c22d9666SAlex Brachet writeUint8(OS, wasm::WASM_SEGMENT_INFO);
233c22d9666SAlex Brachet encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
234c22d9666SAlex Brachet for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
235c22d9666SAlex Brachet writeStringRef(SegmentInfo.Name, SubSection.getStream());
236c22d9666SAlex Brachet encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
237c22d9666SAlex Brachet encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
238c22d9666SAlex Brachet }
239c22d9666SAlex Brachet SubSection.done();
240c22d9666SAlex Brachet }
241c22d9666SAlex Brachet
242c22d9666SAlex Brachet // INIT_FUNCS subsection
243c22d9666SAlex Brachet if (Section.InitFunctions.size()) {
244c22d9666SAlex Brachet writeUint8(OS, wasm::WASM_INIT_FUNCS);
245c22d9666SAlex Brachet encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
246c22d9666SAlex Brachet for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
247c22d9666SAlex Brachet encodeULEB128(Func.Priority, SubSection.getStream());
248c22d9666SAlex Brachet encodeULEB128(Func.Symbol, SubSection.getStream());
249c22d9666SAlex Brachet }
250c22d9666SAlex Brachet SubSection.done();
251c22d9666SAlex Brachet }
252c22d9666SAlex Brachet
253c22d9666SAlex Brachet // COMDAT_INFO subsection
254c22d9666SAlex Brachet if (Section.Comdats.size()) {
255c22d9666SAlex Brachet writeUint8(OS, wasm::WASM_COMDAT_INFO);
256c22d9666SAlex Brachet encodeULEB128(Section.Comdats.size(), SubSection.getStream());
257c22d9666SAlex Brachet for (const auto &C : Section.Comdats) {
258c22d9666SAlex Brachet writeStringRef(C.Name, SubSection.getStream());
259c22d9666SAlex Brachet encodeULEB128(0, SubSection.getStream()); // flags for future use
260c22d9666SAlex Brachet encodeULEB128(C.Entries.size(), SubSection.getStream());
261c22d9666SAlex Brachet for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
262c22d9666SAlex Brachet writeUint8(SubSection.getStream(), Entry.Kind);
263c22d9666SAlex Brachet encodeULEB128(Entry.Index, SubSection.getStream());
264c22d9666SAlex Brachet }
265c22d9666SAlex Brachet }
266c22d9666SAlex Brachet SubSection.done();
267c22d9666SAlex Brachet }
268c22d9666SAlex Brachet }
269c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::NameSection & Section)27085011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
271c22d9666SAlex Brachet WasmYAML::NameSection &Section) {
272c22d9666SAlex Brachet writeStringRef(Section.Name, OS);
273c22d9666SAlex Brachet if (Section.FunctionNames.size()) {
274c22d9666SAlex Brachet writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
275c22d9666SAlex Brachet
276c22d9666SAlex Brachet SubSectionWriter SubSection(OS);
277c22d9666SAlex Brachet
278c22d9666SAlex Brachet encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
279c22d9666SAlex Brachet for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
280c22d9666SAlex Brachet encodeULEB128(NameEntry.Index, SubSection.getStream());
281c22d9666SAlex Brachet writeStringRef(NameEntry.Name, SubSection.getStream());
282c22d9666SAlex Brachet }
283c22d9666SAlex Brachet
284c22d9666SAlex Brachet SubSection.done();
285c22d9666SAlex Brachet }
2861827005cSSam Clegg if (Section.GlobalNames.size()) {
2871827005cSSam Clegg writeUint8(OS, wasm::WASM_NAMES_GLOBAL);
2881827005cSSam Clegg
2891827005cSSam Clegg SubSectionWriter SubSection(OS);
2901827005cSSam Clegg
2911827005cSSam Clegg encodeULEB128(Section.GlobalNames.size(), SubSection.getStream());
2921827005cSSam Clegg for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {
2931827005cSSam Clegg encodeULEB128(NameEntry.Index, SubSection.getStream());
2941827005cSSam Clegg writeStringRef(NameEntry.Name, SubSection.getStream());
2951827005cSSam Clegg }
2961827005cSSam Clegg
2971827005cSSam Clegg SubSection.done();
2981827005cSSam Clegg }
2999a72d3e3SSam Clegg if (Section.DataSegmentNames.size()) {
3009a72d3e3SSam Clegg writeUint8(OS, wasm::WASM_NAMES_DATA_SEGMENT);
3019a72d3e3SSam Clegg
3029a72d3e3SSam Clegg SubSectionWriter SubSection(OS);
3039a72d3e3SSam Clegg
3049a72d3e3SSam Clegg encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());
3059a72d3e3SSam Clegg for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {
3069a72d3e3SSam Clegg encodeULEB128(NameEntry.Index, SubSection.getStream());
3079a72d3e3SSam Clegg writeStringRef(NameEntry.Name, SubSection.getStream());
3089a72d3e3SSam Clegg }
3099a72d3e3SSam Clegg
3109a72d3e3SSam Clegg SubSection.done();
3119a72d3e3SSam Clegg }
312c22d9666SAlex Brachet }
313c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::ProducersSection & Section)31485011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
315c22d9666SAlex Brachet WasmYAML::ProducersSection &Section) {
316c22d9666SAlex Brachet writeStringRef(Section.Name, OS);
317c22d9666SAlex Brachet int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
318c22d9666SAlex Brachet int(!Section.SDKs.empty());
319c22d9666SAlex Brachet if (Fields == 0)
32085011027SGeorge Rimar return;
321c22d9666SAlex Brachet encodeULEB128(Fields, OS);
322c22d9666SAlex Brachet for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
323c22d9666SAlex Brachet std::make_pair(StringRef("processed-by"), &Section.Tools),
324c22d9666SAlex Brachet std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
325c22d9666SAlex Brachet if (Field.second->empty())
326c22d9666SAlex Brachet continue;
327c22d9666SAlex Brachet writeStringRef(Field.first, OS);
328c22d9666SAlex Brachet encodeULEB128(Field.second->size(), OS);
329c22d9666SAlex Brachet for (auto &Entry : *Field.second) {
330c22d9666SAlex Brachet writeStringRef(Entry.Name, OS);
331c22d9666SAlex Brachet writeStringRef(Entry.Version, OS);
332c22d9666SAlex Brachet }
333c22d9666SAlex Brachet }
334c22d9666SAlex Brachet }
335c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::TargetFeaturesSection & Section)33685011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
337c22d9666SAlex Brachet WasmYAML::TargetFeaturesSection &Section) {
338c22d9666SAlex Brachet writeStringRef(Section.Name, OS);
339c22d9666SAlex Brachet encodeULEB128(Section.Features.size(), OS);
340c22d9666SAlex Brachet for (auto &E : Section.Features) {
341c22d9666SAlex Brachet writeUint8(OS, E.Prefix);
342c22d9666SAlex Brachet writeStringRef(E.Name, OS);
343c22d9666SAlex Brachet }
344c22d9666SAlex Brachet }
345c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::CustomSection & Section)34685011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
347c22d9666SAlex Brachet WasmYAML::CustomSection &Section) {
348c22d9666SAlex Brachet if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
34985011027SGeorge Rimar writeSectionContent(OS, *S);
350c22d9666SAlex Brachet } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
35185011027SGeorge Rimar writeSectionContent(OS, *S);
352c22d9666SAlex Brachet } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
35385011027SGeorge Rimar writeSectionContent(OS, *S);
354c22d9666SAlex Brachet } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
35585011027SGeorge Rimar writeSectionContent(OS, *S);
356c22d9666SAlex Brachet } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
35785011027SGeorge Rimar writeSectionContent(OS, *S);
358c22d9666SAlex Brachet } else {
359c22d9666SAlex Brachet writeStringRef(Section.Name, OS);
360c22d9666SAlex Brachet Section.Payload.writeAsBinary(OS);
361c22d9666SAlex Brachet }
362c22d9666SAlex Brachet }
363c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::TypeSection & Section)36485011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
365c22d9666SAlex Brachet WasmYAML::TypeSection &Section) {
366c22d9666SAlex Brachet encodeULEB128(Section.Signatures.size(), OS);
367c22d9666SAlex Brachet uint32_t ExpectedIndex = 0;
368c22d9666SAlex Brachet for (const WasmYAML::Signature &Sig : Section.Signatures) {
369c22d9666SAlex Brachet if (Sig.Index != ExpectedIndex) {
37085011027SGeorge Rimar reportError("unexpected type index: " + Twine(Sig.Index));
37185011027SGeorge Rimar return;
372c22d9666SAlex Brachet }
373c22d9666SAlex Brachet ++ExpectedIndex;
374c22d9666SAlex Brachet writeUint8(OS, Sig.Form);
375c22d9666SAlex Brachet encodeULEB128(Sig.ParamTypes.size(), OS);
376c22d9666SAlex Brachet for (auto ParamType : Sig.ParamTypes)
377c22d9666SAlex Brachet writeUint8(OS, ParamType);
378393d0f79SThomas Lively encodeULEB128(Sig.ReturnTypes.size(), OS);
379393d0f79SThomas Lively for (auto ReturnType : Sig.ReturnTypes)
380393d0f79SThomas Lively writeUint8(OS, ReturnType);
381c22d9666SAlex Brachet }
382c22d9666SAlex Brachet }
383c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::ImportSection & Section)38485011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
385c22d9666SAlex Brachet WasmYAML::ImportSection &Section) {
386c22d9666SAlex Brachet encodeULEB128(Section.Imports.size(), OS);
387c22d9666SAlex Brachet for (const WasmYAML::Import &Import : Section.Imports) {
388c22d9666SAlex Brachet writeStringRef(Import.Module, OS);
389c22d9666SAlex Brachet writeStringRef(Import.Field, OS);
390c22d9666SAlex Brachet writeUint8(OS, Import.Kind);
391c22d9666SAlex Brachet switch (Import.Kind) {
392c22d9666SAlex Brachet case wasm::WASM_EXTERNAL_FUNCTION:
393c22d9666SAlex Brachet encodeULEB128(Import.SigIndex, OS);
394c22d9666SAlex Brachet NumImportedFunctions++;
395c22d9666SAlex Brachet break;
396c22d9666SAlex Brachet case wasm::WASM_EXTERNAL_GLOBAL:
397c22d9666SAlex Brachet writeUint8(OS, Import.GlobalImport.Type);
398c22d9666SAlex Brachet writeUint8(OS, Import.GlobalImport.Mutable);
399c22d9666SAlex Brachet NumImportedGlobals++;
400c22d9666SAlex Brachet break;
4011d891d44SHeejin Ahn case wasm::WASM_EXTERNAL_TAG:
4023ec1760dSHeejin Ahn writeUint8(OS, 0); // Reserved 'attribute' field
4033ec1760dSHeejin Ahn encodeULEB128(Import.SigIndex, OS);
4041d891d44SHeejin Ahn NumImportedTags++;
405c22d9666SAlex Brachet break;
406c22d9666SAlex Brachet case wasm::WASM_EXTERNAL_MEMORY:
407c22d9666SAlex Brachet writeLimits(Import.Memory, OS);
408c22d9666SAlex Brachet break;
409c22d9666SAlex Brachet case wasm::WASM_EXTERNAL_TABLE:
410c22d9666SAlex Brachet writeUint8(OS, Import.TableImport.ElemType);
411c22d9666SAlex Brachet writeLimits(Import.TableImport.TableLimits, OS);
412388fb67bSPaulo Matos NumImportedTables++;
413c22d9666SAlex Brachet break;
414c22d9666SAlex Brachet default:
41585011027SGeorge Rimar reportError("unknown import type: " +Twine(Import.Kind));
41685011027SGeorge Rimar return;
417c22d9666SAlex Brachet }
418c22d9666SAlex Brachet }
419c22d9666SAlex Brachet }
420c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::FunctionSection & Section)42185011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
422c22d9666SAlex Brachet WasmYAML::FunctionSection &Section) {
423c22d9666SAlex Brachet encodeULEB128(Section.FunctionTypes.size(), OS);
42485011027SGeorge Rimar for (uint32_t FuncType : Section.FunctionTypes)
425c22d9666SAlex Brachet encodeULEB128(FuncType, OS);
426c22d9666SAlex Brachet }
427c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::ExportSection & Section)42885011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
429c22d9666SAlex Brachet WasmYAML::ExportSection &Section) {
430c22d9666SAlex Brachet encodeULEB128(Section.Exports.size(), OS);
431c22d9666SAlex Brachet for (const WasmYAML::Export &Export : Section.Exports) {
432c22d9666SAlex Brachet writeStringRef(Export.Name, OS);
433c22d9666SAlex Brachet writeUint8(OS, Export.Kind);
434c22d9666SAlex Brachet encodeULEB128(Export.Index, OS);
435c22d9666SAlex Brachet }
436c22d9666SAlex Brachet }
437c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::StartSection & Section)43885011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
439c22d9666SAlex Brachet WasmYAML::StartSection &Section) {
440c22d9666SAlex Brachet encodeULEB128(Section.StartFunction, OS);
441c22d9666SAlex Brachet }
442c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::TableSection & Section)44385011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
444c22d9666SAlex Brachet WasmYAML::TableSection &Section) {
445c22d9666SAlex Brachet encodeULEB128(Section.Tables.size(), OS);
446388fb67bSPaulo Matos uint32_t ExpectedIndex = NumImportedTables;
447c22d9666SAlex Brachet for (auto &Table : Section.Tables) {
448388fb67bSPaulo Matos if (Table.Index != ExpectedIndex) {
449388fb67bSPaulo Matos reportError("unexpected table index: " + Twine(Table.Index));
450388fb67bSPaulo Matos return;
451388fb67bSPaulo Matos }
452388fb67bSPaulo Matos ++ExpectedIndex;
453c22d9666SAlex Brachet writeUint8(OS, Table.ElemType);
454c22d9666SAlex Brachet writeLimits(Table.TableLimits, OS);
455c22d9666SAlex Brachet }
456c22d9666SAlex Brachet }
457c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::MemorySection & Section)45885011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
459c22d9666SAlex Brachet WasmYAML::MemorySection &Section) {
460c22d9666SAlex Brachet encodeULEB128(Section.Memories.size(), OS);
46185011027SGeorge Rimar for (const WasmYAML::Limits &Mem : Section.Memories)
462c22d9666SAlex Brachet writeLimits(Mem, OS);
463c22d9666SAlex Brachet }
464c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::TagSection & Section)46585011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
4661d891d44SHeejin Ahn WasmYAML::TagSection &Section) {
4673ec1760dSHeejin Ahn encodeULEB128(Section.TagTypes.size(), OS);
4683ec1760dSHeejin Ahn for (uint32_t TagType : Section.TagTypes) {
4693ec1760dSHeejin Ahn writeUint8(OS, 0); // Reserved 'attribute' field
4703ec1760dSHeejin Ahn encodeULEB128(TagType, OS);
471f93426c5SHeejin Ahn }
472f93426c5SHeejin Ahn }
473f93426c5SHeejin Ahn
writeSectionContent(raw_ostream & OS,WasmYAML::GlobalSection & Section)474f93426c5SHeejin Ahn void WasmWriter::writeSectionContent(raw_ostream &OS,
475c22d9666SAlex Brachet WasmYAML::GlobalSection &Section) {
476c22d9666SAlex Brachet encodeULEB128(Section.Globals.size(), OS);
477c22d9666SAlex Brachet uint32_t ExpectedIndex = NumImportedGlobals;
478c22d9666SAlex Brachet for (auto &Global : Section.Globals) {
479c22d9666SAlex Brachet if (Global.Index != ExpectedIndex) {
48085011027SGeorge Rimar reportError("unexpected global index: " + Twine(Global.Index));
48185011027SGeorge Rimar return;
482c22d9666SAlex Brachet }
483c22d9666SAlex Brachet ++ExpectedIndex;
484c22d9666SAlex Brachet writeUint8(OS, Global.Type);
485c22d9666SAlex Brachet writeUint8(OS, Global.Mutable);
486*20f7f733SSam Clegg writeInitExpr(OS, Global.Init);
487c22d9666SAlex Brachet }
488c22d9666SAlex Brachet }
489c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::ElemSection & Section)49085011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
491c22d9666SAlex Brachet WasmYAML::ElemSection &Section) {
492c22d9666SAlex Brachet encodeULEB128(Section.Segments.size(), OS);
493c22d9666SAlex Brachet for (auto &Segment : Section.Segments) {
494a5a3659dSAndy Wingo encodeULEB128(Segment.Flags, OS);
495a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
496a5a3659dSAndy Wingo encodeULEB128(Segment.TableNumber, OS);
497a5a3659dSAndy Wingo
49885011027SGeorge Rimar writeInitExpr(OS, Segment.Offset);
499c22d9666SAlex Brachet
500a5a3659dSAndy Wingo if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
501a5a3659dSAndy Wingo // We only support active function table initializers, for which the elem
502a5a3659dSAndy Wingo // kind is specified to be written as 0x00 and interpreted to mean
503a5a3659dSAndy Wingo // "funcref".
504a5a3659dSAndy Wingo if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {
505a5a3659dSAndy Wingo reportError("unexpected elemkind: " + Twine(Segment.ElemKind));
506a5a3659dSAndy Wingo return;
507a5a3659dSAndy Wingo }
508a5a3659dSAndy Wingo const uint8_t ElemKind = 0;
509a5a3659dSAndy Wingo writeUint8(OS, ElemKind);
510a5a3659dSAndy Wingo }
511a5a3659dSAndy Wingo
512c22d9666SAlex Brachet encodeULEB128(Segment.Functions.size(), OS);
51385011027SGeorge Rimar for (auto &Function : Segment.Functions)
514c22d9666SAlex Brachet encodeULEB128(Function, OS);
515c22d9666SAlex Brachet }
516c22d9666SAlex Brachet }
517c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::CodeSection & Section)51885011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
519c22d9666SAlex Brachet WasmYAML::CodeSection &Section) {
520c22d9666SAlex Brachet encodeULEB128(Section.Functions.size(), OS);
521c22d9666SAlex Brachet uint32_t ExpectedIndex = NumImportedFunctions;
522c22d9666SAlex Brachet for (auto &Func : Section.Functions) {
523c22d9666SAlex Brachet std::string OutString;
524c22d9666SAlex Brachet raw_string_ostream StringStream(OutString);
525c22d9666SAlex Brachet if (Func.Index != ExpectedIndex) {
52685011027SGeorge Rimar reportError("unexpected function index: " + Twine(Func.Index));
52785011027SGeorge Rimar return;
528c22d9666SAlex Brachet }
529c22d9666SAlex Brachet ++ExpectedIndex;
530c22d9666SAlex Brachet
531c22d9666SAlex Brachet encodeULEB128(Func.Locals.size(), StringStream);
532c22d9666SAlex Brachet for (auto &LocalDecl : Func.Locals) {
533c22d9666SAlex Brachet encodeULEB128(LocalDecl.Count, StringStream);
534c22d9666SAlex Brachet writeUint8(StringStream, LocalDecl.Type);
535c22d9666SAlex Brachet }
536c22d9666SAlex Brachet
537c22d9666SAlex Brachet Func.Body.writeAsBinary(StringStream);
538c22d9666SAlex Brachet
539c22d9666SAlex Brachet // Write the section size followed by the content
540c22d9666SAlex Brachet StringStream.flush();
541c22d9666SAlex Brachet encodeULEB128(OutString.size(), OS);
542c22d9666SAlex Brachet OS << OutString;
543c22d9666SAlex Brachet }
544c22d9666SAlex Brachet }
545c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::DataSection & Section)54685011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
547c22d9666SAlex Brachet WasmYAML::DataSection &Section) {
548c22d9666SAlex Brachet encodeULEB128(Section.Segments.size(), OS);
549c22d9666SAlex Brachet for (auto &Segment : Section.Segments) {
550c22d9666SAlex Brachet encodeULEB128(Segment.InitFlags, OS);
551831a143eSAndy Wingo if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
552c22d9666SAlex Brachet encodeULEB128(Segment.MemoryIndex, OS);
553831a143eSAndy Wingo if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)
55485011027SGeorge Rimar writeInitExpr(OS, Segment.Offset);
555c22d9666SAlex Brachet encodeULEB128(Segment.Content.binary_size(), OS);
556c22d9666SAlex Brachet Segment.Content.writeAsBinary(OS);
557c22d9666SAlex Brachet }
558c22d9666SAlex Brachet }
559c22d9666SAlex Brachet
writeSectionContent(raw_ostream & OS,WasmYAML::DataCountSection & Section)56085011027SGeorge Rimar void WasmWriter::writeSectionContent(raw_ostream &OS,
561c22d9666SAlex Brachet WasmYAML::DataCountSection &Section) {
562c22d9666SAlex Brachet encodeULEB128(Section.Count, OS);
563c22d9666SAlex Brachet }
564c22d9666SAlex Brachet
writeRelocSection(raw_ostream & OS,WasmYAML::Section & Sec,uint32_t SectionIndex)56585011027SGeorge Rimar void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
566c22d9666SAlex Brachet uint32_t SectionIndex) {
567c22d9666SAlex Brachet switch (Sec.Type) {
568c22d9666SAlex Brachet case wasm::WASM_SEC_CODE:
569c22d9666SAlex Brachet writeStringRef("reloc.CODE", OS);
570c22d9666SAlex Brachet break;
571c22d9666SAlex Brachet case wasm::WASM_SEC_DATA:
572c22d9666SAlex Brachet writeStringRef("reloc.DATA", OS);
573c22d9666SAlex Brachet break;
574c22d9666SAlex Brachet case wasm::WASM_SEC_CUSTOM: {
5756e1a9b0fSSimon Pilgrim auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
576c22d9666SAlex Brachet writeStringRef(("reloc." + CustomSection->Name).str(), OS);
577c22d9666SAlex Brachet break;
578c22d9666SAlex Brachet }
579c22d9666SAlex Brachet default:
580c22d9666SAlex Brachet llvm_unreachable("not yet implemented");
581c22d9666SAlex Brachet }
582c22d9666SAlex Brachet
583c22d9666SAlex Brachet encodeULEB128(SectionIndex, OS);
584c22d9666SAlex Brachet encodeULEB128(Sec.Relocations.size(), OS);
585c22d9666SAlex Brachet
586c22d9666SAlex Brachet for (auto Reloc : Sec.Relocations) {
587c22d9666SAlex Brachet writeUint8(OS, Reloc.Type);
588c22d9666SAlex Brachet encodeULEB128(Reloc.Offset, OS);
589c22d9666SAlex Brachet encodeULEB128(Reloc.Index, OS);
590875ee937SSam Clegg if (wasm::relocTypeHasAddend(Reloc.Type))
59132e98f05SRichard Smith encodeSLEB128(Reloc.Addend, OS);
592c22d9666SAlex Brachet }
593c22d9666SAlex Brachet }
594c22d9666SAlex Brachet
writeWasm(raw_ostream & OS)5957da559f2SGeorge Rimar bool WasmWriter::writeWasm(raw_ostream &OS) {
596c22d9666SAlex Brachet // Write headers
597c22d9666SAlex Brachet OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
598c22d9666SAlex Brachet writeUint32(OS, Obj.Header.Version);
599c22d9666SAlex Brachet
600c22d9666SAlex Brachet // Write each section
601c22d9666SAlex Brachet llvm::object::WasmSectionOrderChecker Checker;
602c22d9666SAlex Brachet for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
603c22d9666SAlex Brachet StringRef SecName = "";
604c22d9666SAlex Brachet if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
605c22d9666SAlex Brachet SecName = S->Name;
606c22d9666SAlex Brachet if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
60785011027SGeorge Rimar reportError("out of order section type: " + Twine(Sec->Type));
6087da559f2SGeorge Rimar return false;
609c22d9666SAlex Brachet }
610c22d9666SAlex Brachet encodeULEB128(Sec->Type, OS);
611c22d9666SAlex Brachet std::string OutString;
612c22d9666SAlex Brachet raw_string_ostream StringStream(OutString);
61385011027SGeorge Rimar if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
61485011027SGeorge Rimar writeSectionContent(StringStream, *S);
61585011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
61685011027SGeorge Rimar writeSectionContent(StringStream, *S);
61785011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
61885011027SGeorge Rimar writeSectionContent(StringStream, *S);
61985011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
62085011027SGeorge Rimar writeSectionContent(StringStream, *S);
62185011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
62285011027SGeorge Rimar writeSectionContent(StringStream, *S);
62385011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
62485011027SGeorge Rimar writeSectionContent(StringStream, *S);
6251d891d44SHeejin Ahn else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))
62685011027SGeorge Rimar writeSectionContent(StringStream, *S);
627f93426c5SHeejin Ahn else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
628f93426c5SHeejin Ahn writeSectionContent(StringStream, *S);
62985011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
63085011027SGeorge Rimar writeSectionContent(StringStream, *S);
63185011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
63285011027SGeorge Rimar writeSectionContent(StringStream, *S);
63385011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
63485011027SGeorge Rimar writeSectionContent(StringStream, *S);
63585011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
63685011027SGeorge Rimar writeSectionContent(StringStream, *S);
63785011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
63885011027SGeorge Rimar writeSectionContent(StringStream, *S);
63985011027SGeorge Rimar else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
64085011027SGeorge Rimar writeSectionContent(StringStream, *S);
64185011027SGeorge Rimar else
64285011027SGeorge Rimar reportError("unknown section type: " + Twine(Sec->Type));
64385011027SGeorge Rimar
64485011027SGeorge Rimar if (HasError)
6457da559f2SGeorge Rimar return false;
64685011027SGeorge Rimar
647c22d9666SAlex Brachet StringStream.flush();
648c22d9666SAlex Brachet
649c22d9666SAlex Brachet // Write the section size followed by the content
650c22d9666SAlex Brachet encodeULEB128(OutString.size(), OS);
651c22d9666SAlex Brachet OS << OutString;
652c22d9666SAlex Brachet }
653c22d9666SAlex Brachet
654c22d9666SAlex Brachet // write reloc sections for any section that have relocations
655c22d9666SAlex Brachet uint32_t SectionIndex = 0;
656c22d9666SAlex Brachet for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
657c22d9666SAlex Brachet if (Sec->Relocations.empty()) {
658c22d9666SAlex Brachet SectionIndex++;
659c22d9666SAlex Brachet continue;
660c22d9666SAlex Brachet }
661c22d9666SAlex Brachet
662c22d9666SAlex Brachet writeUint8(OS, wasm::WASM_SEC_CUSTOM);
663c22d9666SAlex Brachet std::string OutString;
664c22d9666SAlex Brachet raw_string_ostream StringStream(OutString);
665c22d9666SAlex Brachet writeRelocSection(StringStream, *Sec, SectionIndex++);
666c22d9666SAlex Brachet StringStream.flush();
667c22d9666SAlex Brachet
668c22d9666SAlex Brachet encodeULEB128(OutString.size(), OS);
669c22d9666SAlex Brachet OS << OutString;
670c22d9666SAlex Brachet }
671c22d9666SAlex Brachet
6727da559f2SGeorge Rimar return true;
673c22d9666SAlex Brachet }
674c22d9666SAlex Brachet
675c22d9666SAlex Brachet namespace llvm {
676c22d9666SAlex Brachet namespace yaml {
677c22d9666SAlex Brachet
yaml2wasm(WasmYAML::Object & Doc,raw_ostream & Out,ErrorHandler EH)67885011027SGeorge Rimar bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
67985011027SGeorge Rimar WasmWriter Writer(Doc, EH);
680c22d9666SAlex Brachet return Writer.writeWasm(Out);
681c22d9666SAlex Brachet }
682c22d9666SAlex Brachet
683c22d9666SAlex Brachet } // namespace yaml
684c22d9666SAlex Brachet } // namespace llvm
685