[InstCombine] Signed saturation patterns
[llvm-complete.git] / lib / ObjectYAML / WasmEmitter.cpp
blobdebc040587a87fa9c9a625eeb608ce43bf52e65a
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 encodeULEB128(Sig.ReturnTypes.size(), OS);
338 for (auto ReturnType : Sig.ReturnTypes)
339 writeUint8(OS, ReturnType);
343 void WasmWriter::writeSectionContent(raw_ostream &OS,
344 WasmYAML::ImportSection &Section) {
345 encodeULEB128(Section.Imports.size(), OS);
346 for (const WasmYAML::Import &Import : Section.Imports) {
347 writeStringRef(Import.Module, OS);
348 writeStringRef(Import.Field, OS);
349 writeUint8(OS, Import.Kind);
350 switch (Import.Kind) {
351 case wasm::WASM_EXTERNAL_FUNCTION:
352 encodeULEB128(Import.SigIndex, OS);
353 NumImportedFunctions++;
354 break;
355 case wasm::WASM_EXTERNAL_GLOBAL:
356 writeUint8(OS, Import.GlobalImport.Type);
357 writeUint8(OS, Import.GlobalImport.Mutable);
358 NumImportedGlobals++;
359 break;
360 case wasm::WASM_EXTERNAL_EVENT:
361 writeUint32(OS, Import.EventImport.Attribute);
362 writeUint32(OS, Import.EventImport.SigIndex);
363 NumImportedGlobals++;
364 break;
365 case wasm::WASM_EXTERNAL_MEMORY:
366 writeLimits(Import.Memory, OS);
367 break;
368 case wasm::WASM_EXTERNAL_TABLE:
369 writeUint8(OS, Import.TableImport.ElemType);
370 writeLimits(Import.TableImport.TableLimits, OS);
371 break;
372 default:
373 reportError("unknown import type: " +Twine(Import.Kind));
374 return;
379 void WasmWriter::writeSectionContent(raw_ostream &OS,
380 WasmYAML::FunctionSection &Section) {
381 encodeULEB128(Section.FunctionTypes.size(), OS);
382 for (uint32_t FuncType : Section.FunctionTypes)
383 encodeULEB128(FuncType, OS);
386 void WasmWriter::writeSectionContent(raw_ostream &OS,
387 WasmYAML::ExportSection &Section) {
388 encodeULEB128(Section.Exports.size(), OS);
389 for (const WasmYAML::Export &Export : Section.Exports) {
390 writeStringRef(Export.Name, OS);
391 writeUint8(OS, Export.Kind);
392 encodeULEB128(Export.Index, OS);
396 void WasmWriter::writeSectionContent(raw_ostream &OS,
397 WasmYAML::StartSection &Section) {
398 encodeULEB128(Section.StartFunction, OS);
401 void WasmWriter::writeSectionContent(raw_ostream &OS,
402 WasmYAML::TableSection &Section) {
403 encodeULEB128(Section.Tables.size(), OS);
404 for (auto &Table : Section.Tables) {
405 writeUint8(OS, Table.ElemType);
406 writeLimits(Table.TableLimits, OS);
410 void WasmWriter::writeSectionContent(raw_ostream &OS,
411 WasmYAML::MemorySection &Section) {
412 encodeULEB128(Section.Memories.size(), OS);
413 for (const WasmYAML::Limits &Mem : Section.Memories)
414 writeLimits(Mem, OS);
417 void WasmWriter::writeSectionContent(raw_ostream &OS,
418 WasmYAML::GlobalSection &Section) {
419 encodeULEB128(Section.Globals.size(), OS);
420 uint32_t ExpectedIndex = NumImportedGlobals;
421 for (auto &Global : Section.Globals) {
422 if (Global.Index != ExpectedIndex) {
423 reportError("unexpected global index: " + Twine(Global.Index));
424 return;
426 ++ExpectedIndex;
427 writeUint8(OS, Global.Type);
428 writeUint8(OS, Global.Mutable);
429 writeInitExpr(OS, Global.InitExpr);
433 void WasmWriter::writeSectionContent(raw_ostream &OS,
434 WasmYAML::EventSection &Section) {
435 encodeULEB128(Section.Events.size(), OS);
436 uint32_t ExpectedIndex = NumImportedEvents;
437 for (auto &Event : Section.Events) {
438 if (Event.Index != ExpectedIndex) {
439 reportError("unexpected event index: " + Twine(Event.Index));
440 return;
442 ++ExpectedIndex;
443 encodeULEB128(Event.Attribute, OS);
444 encodeULEB128(Event.SigIndex, OS);
448 void WasmWriter::writeSectionContent(raw_ostream &OS,
449 WasmYAML::ElemSection &Section) {
450 encodeULEB128(Section.Segments.size(), OS);
451 for (auto &Segment : Section.Segments) {
452 encodeULEB128(Segment.TableIndex, OS);
453 writeInitExpr(OS, Segment.Offset);
455 encodeULEB128(Segment.Functions.size(), OS);
456 for (auto &Function : Segment.Functions)
457 encodeULEB128(Function, OS);
461 void WasmWriter::writeSectionContent(raw_ostream &OS,
462 WasmYAML::CodeSection &Section) {
463 encodeULEB128(Section.Functions.size(), OS);
464 uint32_t ExpectedIndex = NumImportedFunctions;
465 for (auto &Func : Section.Functions) {
466 std::string OutString;
467 raw_string_ostream StringStream(OutString);
468 if (Func.Index != ExpectedIndex) {
469 reportError("unexpected function index: " + Twine(Func.Index));
470 return;
472 ++ExpectedIndex;
474 encodeULEB128(Func.Locals.size(), StringStream);
475 for (auto &LocalDecl : Func.Locals) {
476 encodeULEB128(LocalDecl.Count, StringStream);
477 writeUint8(StringStream, LocalDecl.Type);
480 Func.Body.writeAsBinary(StringStream);
482 // Write the section size followed by the content
483 StringStream.flush();
484 encodeULEB128(OutString.size(), OS);
485 OS << OutString;
489 void WasmWriter::writeSectionContent(raw_ostream &OS,
490 WasmYAML::DataSection &Section) {
491 encodeULEB128(Section.Segments.size(), OS);
492 for (auto &Segment : Section.Segments) {
493 encodeULEB128(Segment.InitFlags, OS);
494 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
495 encodeULEB128(Segment.MemoryIndex, OS);
496 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
497 writeInitExpr(OS, Segment.Offset);
498 encodeULEB128(Segment.Content.binary_size(), OS);
499 Segment.Content.writeAsBinary(OS);
503 void WasmWriter::writeSectionContent(raw_ostream &OS,
504 WasmYAML::DataCountSection &Section) {
505 encodeULEB128(Section.Count, OS);
508 void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
509 uint32_t SectionIndex) {
510 switch (Sec.Type) {
511 case wasm::WASM_SEC_CODE:
512 writeStringRef("reloc.CODE", OS);
513 break;
514 case wasm::WASM_SEC_DATA:
515 writeStringRef("reloc.DATA", OS);
516 break;
517 case wasm::WASM_SEC_CUSTOM: {
518 auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
519 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
520 break;
522 default:
523 llvm_unreachable("not yet implemented");
526 encodeULEB128(SectionIndex, OS);
527 encodeULEB128(Sec.Relocations.size(), OS);
529 for (auto Reloc : Sec.Relocations) {
530 writeUint8(OS, Reloc.Type);
531 encodeULEB128(Reloc.Offset, OS);
532 encodeULEB128(Reloc.Index, OS);
533 switch (Reloc.Type) {
534 case wasm::R_WASM_MEMORY_ADDR_LEB:
535 case wasm::R_WASM_MEMORY_ADDR_SLEB:
536 case wasm::R_WASM_MEMORY_ADDR_I32:
537 case wasm::R_WASM_FUNCTION_OFFSET_I32:
538 case wasm::R_WASM_SECTION_OFFSET_I32:
539 encodeULEB128(Reloc.Addend, OS);
544 bool WasmWriter::writeWasm(raw_ostream &OS) {
545 // Write headers
546 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
547 writeUint32(OS, Obj.Header.Version);
549 // Write each section
550 llvm::object::WasmSectionOrderChecker Checker;
551 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
552 StringRef SecName = "";
553 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
554 SecName = S->Name;
555 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
556 reportError("out of order section type: " + Twine(Sec->Type));
557 return false;
559 encodeULEB128(Sec->Type, OS);
560 std::string OutString;
561 raw_string_ostream StringStream(OutString);
562 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
563 writeSectionContent(StringStream, *S);
564 else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
565 writeSectionContent(StringStream, *S);
566 else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
567 writeSectionContent(StringStream, *S);
568 else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
569 writeSectionContent(StringStream, *S);
570 else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
571 writeSectionContent(StringStream, *S);
572 else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
573 writeSectionContent(StringStream, *S);
574 else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
575 writeSectionContent(StringStream, *S);
576 else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get()))
577 writeSectionContent(StringStream, *S);
578 else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
579 writeSectionContent(StringStream, *S);
580 else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
581 writeSectionContent(StringStream, *S);
582 else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
583 writeSectionContent(StringStream, *S);
584 else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
585 writeSectionContent(StringStream, *S);
586 else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
587 writeSectionContent(StringStream, *S);
588 else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
589 writeSectionContent(StringStream, *S);
590 else
591 reportError("unknown section type: " + Twine(Sec->Type));
593 if (HasError)
594 return false;
596 StringStream.flush();
598 // Write the section size followed by the content
599 encodeULEB128(OutString.size(), OS);
600 OS << OutString;
603 // write reloc sections for any section that have relocations
604 uint32_t SectionIndex = 0;
605 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
606 if (Sec->Relocations.empty()) {
607 SectionIndex++;
608 continue;
611 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
612 std::string OutString;
613 raw_string_ostream StringStream(OutString);
614 writeRelocSection(StringStream, *Sec, SectionIndex++);
615 StringStream.flush();
617 encodeULEB128(OutString.size(), OS);
618 OS << OutString;
621 return true;
624 namespace llvm {
625 namespace yaml {
627 bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
628 WasmWriter Writer(Doc, EH);
629 return Writer.writeWasm(Out);
632 } // namespace yaml
633 } // namespace llvm