Recommit r373598 "[yaml2obj/obj2yaml] - Add support for SHT_LLVM_ADDRSIG sections."
[llvm-complete.git] / lib / ObjectYAML / WasmEmitter.cpp
blob42c57d42ad786085da50f35e9fa037bad06d9b94
1 //===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// The Wasm component of yaml2obj.
11 ///
12 //===----------------------------------------------------------------------===//
15 #include "llvm/Object/Wasm.h"
16 #include "llvm/ObjectYAML/ObjectYAML.h"
17 #include "llvm/ObjectYAML/yaml2obj.h"
18 #include "llvm/Support/Endian.h"
19 #include "llvm/Support/LEB128.h"
21 using namespace llvm;
23 namespace {
24 /// This parses a yaml stream that represents a Wasm object file.
25 /// See docs/yaml2obj for the yaml scheema.
26 class WasmWriter {
27 public:
28 WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)
29 : Obj(Obj), ErrHandler(EH) {}
30 bool writeWasm(raw_ostream &OS);
32 private:
33 void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
34 uint32_t SectionIndex);
36 void writeInitExpr(raw_ostream &OS, const wasm::WasmInitExpr &InitExpr);
38 void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
39 void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
40 void writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
41 void writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
42 void writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
43 void writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
44 void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
45 void writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
46 void writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
47 void writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
48 void writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
49 void writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
50 void writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
51 void writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
53 // Custom section types
54 void writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
55 void writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
56 void writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
57 void writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
58 void writeSectionContent(raw_ostream &OS,
59 WasmYAML::TargetFeaturesSection &Section);
60 WasmYAML::Object &Obj;
61 uint32_t NumImportedFunctions = 0;
62 uint32_t NumImportedGlobals = 0;
63 uint32_t NumImportedEvents = 0;
65 bool HasError = false;
66 yaml::ErrorHandler ErrHandler;
67 void reportError(const Twine &Msg);
70 class SubSectionWriter {
71 raw_ostream &OS;
72 std::string OutString;
73 raw_string_ostream StringStream;
75 public:
76 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
78 void done() {
79 StringStream.flush();
80 encodeULEB128(OutString.size(), OS);
81 OS << OutString;
82 OutString.clear();
85 raw_ostream &getStream() { return StringStream; }
88 } // end anonymous namespace
90 static int writeUint64(raw_ostream &OS, uint64_t Value) {
91 char Data[sizeof(Value)];
92 support::endian::write64le(Data, Value);
93 OS.write(Data, sizeof(Data));
94 return 0;
97 static int writeUint32(raw_ostream &OS, uint32_t Value) {
98 char Data[sizeof(Value)];
99 support::endian::write32le(Data, Value);
100 OS.write(Data, sizeof(Data));
101 return 0;
104 static int writeUint8(raw_ostream &OS, uint8_t Value) {
105 char Data[sizeof(Value)];
106 memcpy(Data, &Value, sizeof(Data));
107 OS.write(Data, sizeof(Data));
108 return 0;
111 static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
112 encodeULEB128(Str.size(), OS);
113 OS << Str;
114 return 0;
117 static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
118 writeUint8(OS, Lim.Flags);
119 encodeULEB128(Lim.Initial, OS);
120 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
121 encodeULEB128(Lim.Maximum, OS);
122 return 0;
125 void WasmWriter::reportError(const Twine &Msg) {
126 ErrHandler(Msg);
127 HasError = true;
130 void WasmWriter::writeInitExpr(raw_ostream &OS,
131 const wasm::WasmInitExpr &InitExpr) {
132 writeUint8(OS, InitExpr.Opcode);
133 switch (InitExpr.Opcode) {
134 case wasm::WASM_OPCODE_I32_CONST:
135 encodeSLEB128(InitExpr.Value.Int32, OS);
136 break;
137 case wasm::WASM_OPCODE_I64_CONST:
138 encodeSLEB128(InitExpr.Value.Int64, OS);
139 break;
140 case wasm::WASM_OPCODE_F32_CONST:
141 writeUint32(OS, InitExpr.Value.Float32);
142 break;
143 case wasm::WASM_OPCODE_F64_CONST:
144 writeUint64(OS, InitExpr.Value.Float64);
145 break;
146 case wasm::WASM_OPCODE_GLOBAL_GET:
147 encodeULEB128(InitExpr.Value.Global, OS);
148 break;
149 default:
150 reportError("unknown opcode in init_expr: " + Twine(InitExpr.Opcode));
151 return;
153 writeUint8(OS, wasm::WASM_OPCODE_END);
156 void WasmWriter::writeSectionContent(raw_ostream &OS,
157 WasmYAML::DylinkSection &Section) {
158 writeStringRef(Section.Name, OS);
159 encodeULEB128(Section.MemorySize, OS);
160 encodeULEB128(Section.MemoryAlignment, OS);
161 encodeULEB128(Section.TableSize, OS);
162 encodeULEB128(Section.TableAlignment, OS);
163 encodeULEB128(Section.Needed.size(), OS);
164 for (StringRef Needed : Section.Needed)
165 writeStringRef(Needed, OS);
168 void WasmWriter::writeSectionContent(raw_ostream &OS,
169 WasmYAML::LinkingSection &Section) {
170 writeStringRef(Section.Name, OS);
171 encodeULEB128(Section.Version, OS);
173 SubSectionWriter SubSection(OS);
175 // SYMBOL_TABLE subsection
176 if (Section.SymbolTable.size()) {
177 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
179 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
180 #ifndef NDEBUG
181 uint32_t SymbolIndex = 0;
182 #endif
183 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
184 assert(Info.Index == SymbolIndex++);
185 writeUint8(SubSection.getStream(), Info.Kind);
186 encodeULEB128(Info.Flags, SubSection.getStream());
187 switch (Info.Kind) {
188 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
189 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
190 case wasm::WASM_SYMBOL_TYPE_EVENT:
191 encodeULEB128(Info.ElementIndex, SubSection.getStream());
192 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
193 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
194 writeStringRef(Info.Name, SubSection.getStream());
195 break;
196 case wasm::WASM_SYMBOL_TYPE_DATA:
197 writeStringRef(Info.Name, SubSection.getStream());
198 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
199 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
200 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
201 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
203 break;
204 case wasm::WASM_SYMBOL_TYPE_SECTION:
205 encodeULEB128(Info.ElementIndex, SubSection.getStream());
206 break;
207 default:
208 llvm_unreachable("unexpected kind");
212 SubSection.done();
215 // SEGMENT_NAMES subsection
216 if (Section.SegmentInfos.size()) {
217 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
218 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
219 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
220 writeStringRef(SegmentInfo.Name, SubSection.getStream());
221 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
222 encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
224 SubSection.done();
227 // INIT_FUNCS subsection
228 if (Section.InitFunctions.size()) {
229 writeUint8(OS, wasm::WASM_INIT_FUNCS);
230 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
231 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
232 encodeULEB128(Func.Priority, SubSection.getStream());
233 encodeULEB128(Func.Symbol, SubSection.getStream());
235 SubSection.done();
238 // COMDAT_INFO subsection
239 if (Section.Comdats.size()) {
240 writeUint8(OS, wasm::WASM_COMDAT_INFO);
241 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
242 for (const auto &C : Section.Comdats) {
243 writeStringRef(C.Name, SubSection.getStream());
244 encodeULEB128(0, SubSection.getStream()); // flags for future use
245 encodeULEB128(C.Entries.size(), SubSection.getStream());
246 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
247 writeUint8(SubSection.getStream(), Entry.Kind);
248 encodeULEB128(Entry.Index, SubSection.getStream());
251 SubSection.done();
255 void WasmWriter::writeSectionContent(raw_ostream &OS,
256 WasmYAML::NameSection &Section) {
257 writeStringRef(Section.Name, OS);
258 if (Section.FunctionNames.size()) {
259 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
261 SubSectionWriter SubSection(OS);
263 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
264 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
265 encodeULEB128(NameEntry.Index, SubSection.getStream());
266 writeStringRef(NameEntry.Name, SubSection.getStream());
269 SubSection.done();
273 void WasmWriter::writeSectionContent(raw_ostream &OS,
274 WasmYAML::ProducersSection &Section) {
275 writeStringRef(Section.Name, OS);
276 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
277 int(!Section.SDKs.empty());
278 if (Fields == 0)
279 return;
280 encodeULEB128(Fields, OS);
281 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
282 std::make_pair(StringRef("processed-by"), &Section.Tools),
283 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
284 if (Field.second->empty())
285 continue;
286 writeStringRef(Field.first, OS);
287 encodeULEB128(Field.second->size(), OS);
288 for (auto &Entry : *Field.second) {
289 writeStringRef(Entry.Name, OS);
290 writeStringRef(Entry.Version, OS);
295 void WasmWriter::writeSectionContent(raw_ostream &OS,
296 WasmYAML::TargetFeaturesSection &Section) {
297 writeStringRef(Section.Name, OS);
298 encodeULEB128(Section.Features.size(), OS);
299 for (auto &E : Section.Features) {
300 writeUint8(OS, E.Prefix);
301 writeStringRef(E.Name, OS);
305 void WasmWriter::writeSectionContent(raw_ostream &OS,
306 WasmYAML::CustomSection &Section) {
307 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
308 writeSectionContent(OS, *S);
309 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
310 writeSectionContent(OS, *S);
311 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
312 writeSectionContent(OS, *S);
313 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
314 writeSectionContent(OS, *S);
315 } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
316 writeSectionContent(OS, *S);
317 } else {
318 writeStringRef(Section.Name, OS);
319 Section.Payload.writeAsBinary(OS);
323 void WasmWriter::writeSectionContent(raw_ostream &OS,
324 WasmYAML::TypeSection &Section) {
325 encodeULEB128(Section.Signatures.size(), OS);
326 uint32_t ExpectedIndex = 0;
327 for (const WasmYAML::Signature &Sig : Section.Signatures) {
328 if (Sig.Index != ExpectedIndex) {
329 reportError("unexpected type index: " + Twine(Sig.Index));
330 return;
332 ++ExpectedIndex;
333 writeUint8(OS, Sig.Form);
334 encodeULEB128(Sig.ParamTypes.size(), OS);
335 for (auto ParamType : Sig.ParamTypes)
336 writeUint8(OS, ParamType);
337 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
338 encodeULEB128(0, OS);
339 } else {
340 encodeULEB128(1, OS);
341 writeUint8(OS, Sig.ReturnType);
346 void WasmWriter::writeSectionContent(raw_ostream &OS,
347 WasmYAML::ImportSection &Section) {
348 encodeULEB128(Section.Imports.size(), OS);
349 for (const WasmYAML::Import &Import : Section.Imports) {
350 writeStringRef(Import.Module, OS);
351 writeStringRef(Import.Field, OS);
352 writeUint8(OS, Import.Kind);
353 switch (Import.Kind) {
354 case wasm::WASM_EXTERNAL_FUNCTION:
355 encodeULEB128(Import.SigIndex, OS);
356 NumImportedFunctions++;
357 break;
358 case wasm::WASM_EXTERNAL_GLOBAL:
359 writeUint8(OS, Import.GlobalImport.Type);
360 writeUint8(OS, Import.GlobalImport.Mutable);
361 NumImportedGlobals++;
362 break;
363 case wasm::WASM_EXTERNAL_EVENT:
364 writeUint32(OS, Import.EventImport.Attribute);
365 writeUint32(OS, Import.EventImport.SigIndex);
366 NumImportedGlobals++;
367 break;
368 case wasm::WASM_EXTERNAL_MEMORY:
369 writeLimits(Import.Memory, OS);
370 break;
371 case wasm::WASM_EXTERNAL_TABLE:
372 writeUint8(OS, Import.TableImport.ElemType);
373 writeLimits(Import.TableImport.TableLimits, OS);
374 break;
375 default:
376 reportError("unknown import type: " +Twine(Import.Kind));
377 return;
382 void WasmWriter::writeSectionContent(raw_ostream &OS,
383 WasmYAML::FunctionSection &Section) {
384 encodeULEB128(Section.FunctionTypes.size(), OS);
385 for (uint32_t FuncType : Section.FunctionTypes)
386 encodeULEB128(FuncType, OS);
389 void WasmWriter::writeSectionContent(raw_ostream &OS,
390 WasmYAML::ExportSection &Section) {
391 encodeULEB128(Section.Exports.size(), OS);
392 for (const WasmYAML::Export &Export : Section.Exports) {
393 writeStringRef(Export.Name, OS);
394 writeUint8(OS, Export.Kind);
395 encodeULEB128(Export.Index, OS);
399 void WasmWriter::writeSectionContent(raw_ostream &OS,
400 WasmYAML::StartSection &Section) {
401 encodeULEB128(Section.StartFunction, OS);
404 void WasmWriter::writeSectionContent(raw_ostream &OS,
405 WasmYAML::TableSection &Section) {
406 encodeULEB128(Section.Tables.size(), OS);
407 for (auto &Table : Section.Tables) {
408 writeUint8(OS, Table.ElemType);
409 writeLimits(Table.TableLimits, OS);
413 void WasmWriter::writeSectionContent(raw_ostream &OS,
414 WasmYAML::MemorySection &Section) {
415 encodeULEB128(Section.Memories.size(), OS);
416 for (const WasmYAML::Limits &Mem : Section.Memories)
417 writeLimits(Mem, OS);
420 void WasmWriter::writeSectionContent(raw_ostream &OS,
421 WasmYAML::GlobalSection &Section) {
422 encodeULEB128(Section.Globals.size(), OS);
423 uint32_t ExpectedIndex = NumImportedGlobals;
424 for (auto &Global : Section.Globals) {
425 if (Global.Index != ExpectedIndex) {
426 reportError("unexpected global index: " + Twine(Global.Index));
427 return;
429 ++ExpectedIndex;
430 writeUint8(OS, Global.Type);
431 writeUint8(OS, Global.Mutable);
432 writeInitExpr(OS, Global.InitExpr);
436 void WasmWriter::writeSectionContent(raw_ostream &OS,
437 WasmYAML::EventSection &Section) {
438 encodeULEB128(Section.Events.size(), OS);
439 uint32_t ExpectedIndex = NumImportedEvents;
440 for (auto &Event : Section.Events) {
441 if (Event.Index != ExpectedIndex) {
442 reportError("unexpected event index: " + Twine(Event.Index));
443 return;
445 ++ExpectedIndex;
446 encodeULEB128(Event.Attribute, OS);
447 encodeULEB128(Event.SigIndex, OS);
451 void WasmWriter::writeSectionContent(raw_ostream &OS,
452 WasmYAML::ElemSection &Section) {
453 encodeULEB128(Section.Segments.size(), OS);
454 for (auto &Segment : Section.Segments) {
455 encodeULEB128(Segment.TableIndex, OS);
456 writeInitExpr(OS, Segment.Offset);
458 encodeULEB128(Segment.Functions.size(), OS);
459 for (auto &Function : Segment.Functions)
460 encodeULEB128(Function, OS);
464 void WasmWriter::writeSectionContent(raw_ostream &OS,
465 WasmYAML::CodeSection &Section) {
466 encodeULEB128(Section.Functions.size(), OS);
467 uint32_t ExpectedIndex = NumImportedFunctions;
468 for (auto &Func : Section.Functions) {
469 std::string OutString;
470 raw_string_ostream StringStream(OutString);
471 if (Func.Index != ExpectedIndex) {
472 reportError("unexpected function index: " + Twine(Func.Index));
473 return;
475 ++ExpectedIndex;
477 encodeULEB128(Func.Locals.size(), StringStream);
478 for (auto &LocalDecl : Func.Locals) {
479 encodeULEB128(LocalDecl.Count, StringStream);
480 writeUint8(StringStream, LocalDecl.Type);
483 Func.Body.writeAsBinary(StringStream);
485 // Write the section size followed by the content
486 StringStream.flush();
487 encodeULEB128(OutString.size(), OS);
488 OS << OutString;
492 void WasmWriter::writeSectionContent(raw_ostream &OS,
493 WasmYAML::DataSection &Section) {
494 encodeULEB128(Section.Segments.size(), OS);
495 for (auto &Segment : Section.Segments) {
496 encodeULEB128(Segment.InitFlags, OS);
497 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
498 encodeULEB128(Segment.MemoryIndex, OS);
499 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
500 writeInitExpr(OS, Segment.Offset);
501 encodeULEB128(Segment.Content.binary_size(), OS);
502 Segment.Content.writeAsBinary(OS);
506 void WasmWriter::writeSectionContent(raw_ostream &OS,
507 WasmYAML::DataCountSection &Section) {
508 encodeULEB128(Section.Count, OS);
511 void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
512 uint32_t SectionIndex) {
513 switch (Sec.Type) {
514 case wasm::WASM_SEC_CODE:
515 writeStringRef("reloc.CODE", OS);
516 break;
517 case wasm::WASM_SEC_DATA:
518 writeStringRef("reloc.DATA", OS);
519 break;
520 case wasm::WASM_SEC_CUSTOM: {
521 auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
522 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
523 break;
525 default:
526 llvm_unreachable("not yet implemented");
529 encodeULEB128(SectionIndex, OS);
530 encodeULEB128(Sec.Relocations.size(), OS);
532 for (auto Reloc : Sec.Relocations) {
533 writeUint8(OS, Reloc.Type);
534 encodeULEB128(Reloc.Offset, OS);
535 encodeULEB128(Reloc.Index, OS);
536 switch (Reloc.Type) {
537 case wasm::R_WASM_MEMORY_ADDR_LEB:
538 case wasm::R_WASM_MEMORY_ADDR_SLEB:
539 case wasm::R_WASM_MEMORY_ADDR_I32:
540 case wasm::R_WASM_FUNCTION_OFFSET_I32:
541 case wasm::R_WASM_SECTION_OFFSET_I32:
542 encodeULEB128(Reloc.Addend, OS);
547 bool WasmWriter::writeWasm(raw_ostream &OS) {
548 // Write headers
549 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
550 writeUint32(OS, Obj.Header.Version);
552 // Write each section
553 llvm::object::WasmSectionOrderChecker Checker;
554 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
555 StringRef SecName = "";
556 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
557 SecName = S->Name;
558 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
559 reportError("out of order section type: " + Twine(Sec->Type));
560 return false;
562 encodeULEB128(Sec->Type, OS);
563 std::string OutString;
564 raw_string_ostream StringStream(OutString);
565 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
566 writeSectionContent(StringStream, *S);
567 else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
568 writeSectionContent(StringStream, *S);
569 else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
570 writeSectionContent(StringStream, *S);
571 else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
572 writeSectionContent(StringStream, *S);
573 else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
574 writeSectionContent(StringStream, *S);
575 else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
576 writeSectionContent(StringStream, *S);
577 else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
578 writeSectionContent(StringStream, *S);
579 else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get()))
580 writeSectionContent(StringStream, *S);
581 else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
582 writeSectionContent(StringStream, *S);
583 else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
584 writeSectionContent(StringStream, *S);
585 else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
586 writeSectionContent(StringStream, *S);
587 else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
588 writeSectionContent(StringStream, *S);
589 else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
590 writeSectionContent(StringStream, *S);
591 else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
592 writeSectionContent(StringStream, *S);
593 else
594 reportError("unknown section type: " + Twine(Sec->Type));
596 if (HasError)
597 return false;
599 StringStream.flush();
601 // Write the section size followed by the content
602 encodeULEB128(OutString.size(), OS);
603 OS << OutString;
606 // write reloc sections for any section that have relocations
607 uint32_t SectionIndex = 0;
608 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
609 if (Sec->Relocations.empty()) {
610 SectionIndex++;
611 continue;
614 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
615 std::string OutString;
616 raw_string_ostream StringStream(OutString);
617 writeRelocSection(StringStream, *Sec, SectionIndex++);
618 StringStream.flush();
620 encodeULEB128(OutString.size(), OS);
621 OS << OutString;
624 return true;
627 namespace llvm {
628 namespace yaml {
630 bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
631 WasmWriter Writer(Doc, EH);
632 return Writer.writeWasm(Out);
635 } // namespace yaml
636 } // namespace llvm