[ARM] Generate 8.1-m CSINC, CSNEG and CSINV instructions.
[llvm-core.git] / lib / ObjectYAML / WasmEmitter.cpp
blob5769d7b895965bd7491a0455d74eab4043ee82b7
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) : Obj(Obj) {}
29 int writeWasm(raw_ostream &OS);
31 private:
32 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
33 uint32_t SectionIndex);
35 int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
36 int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
37 int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
38 int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
39 int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
40 int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
41 int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
42 int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
43 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
44 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
45 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
46 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
47 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
48 int writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
50 // Custom section types
51 int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
52 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
53 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
54 int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
55 int writeSectionContent(raw_ostream &OS,
56 WasmYAML::TargetFeaturesSection &Section);
57 WasmYAML::Object &Obj;
58 uint32_t NumImportedFunctions = 0;
59 uint32_t NumImportedGlobals = 0;
60 uint32_t NumImportedEvents = 0;
63 class SubSectionWriter {
64 raw_ostream &OS;
65 std::string OutString;
66 raw_string_ostream StringStream;
68 public:
69 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
71 void done() {
72 StringStream.flush();
73 encodeULEB128(OutString.size(), OS);
74 OS << OutString;
75 OutString.clear();
78 raw_ostream &getStream() { return StringStream; }
81 } // end anonymous namespace
83 static int writeUint64(raw_ostream &OS, uint64_t Value) {
84 char Data[sizeof(Value)];
85 support::endian::write64le(Data, Value);
86 OS.write(Data, sizeof(Data));
87 return 0;
90 static int writeUint32(raw_ostream &OS, uint32_t Value) {
91 char Data[sizeof(Value)];
92 support::endian::write32le(Data, Value);
93 OS.write(Data, sizeof(Data));
94 return 0;
97 static int writeUint8(raw_ostream &OS, uint8_t Value) {
98 char Data[sizeof(Value)];
99 memcpy(Data, &Value, sizeof(Data));
100 OS.write(Data, sizeof(Data));
101 return 0;
104 static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
105 encodeULEB128(Str.size(), OS);
106 OS << Str;
107 return 0;
110 static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
111 writeUint8(OS, Lim.Flags);
112 encodeULEB128(Lim.Initial, OS);
113 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
114 encodeULEB128(Lim.Maximum, OS);
115 return 0;
118 static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
119 writeUint8(OS, InitExpr.Opcode);
120 switch (InitExpr.Opcode) {
121 case wasm::WASM_OPCODE_I32_CONST:
122 encodeSLEB128(InitExpr.Value.Int32, OS);
123 break;
124 case wasm::WASM_OPCODE_I64_CONST:
125 encodeSLEB128(InitExpr.Value.Int64, OS);
126 break;
127 case wasm::WASM_OPCODE_F32_CONST:
128 writeUint32(OS, InitExpr.Value.Float32);
129 break;
130 case wasm::WASM_OPCODE_F64_CONST:
131 writeUint64(OS, InitExpr.Value.Float64);
132 break;
133 case wasm::WASM_OPCODE_GLOBAL_GET:
134 encodeULEB128(InitExpr.Value.Global, OS);
135 break;
136 default:
137 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
138 return 1;
140 writeUint8(OS, wasm::WASM_OPCODE_END);
141 return 0;
144 int WasmWriter::writeSectionContent(raw_ostream &OS,
145 WasmYAML::DylinkSection &Section) {
146 writeStringRef(Section.Name, OS);
147 encodeULEB128(Section.MemorySize, OS);
148 encodeULEB128(Section.MemoryAlignment, OS);
149 encodeULEB128(Section.TableSize, OS);
150 encodeULEB128(Section.TableAlignment, OS);
151 encodeULEB128(Section.Needed.size(), OS);
152 for (StringRef Needed : Section.Needed) {
153 writeStringRef(Needed, OS);
155 return 0;
158 int WasmWriter::writeSectionContent(raw_ostream &OS,
159 WasmYAML::LinkingSection &Section) {
160 writeStringRef(Section.Name, OS);
161 encodeULEB128(Section.Version, OS);
163 SubSectionWriter SubSection(OS);
165 // SYMBOL_TABLE subsection
166 if (Section.SymbolTable.size()) {
167 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
169 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
170 #ifndef NDEBUG
171 uint32_t SymbolIndex = 0;
172 #endif
173 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
174 assert(Info.Index == SymbolIndex++);
175 writeUint8(SubSection.getStream(), Info.Kind);
176 encodeULEB128(Info.Flags, SubSection.getStream());
177 switch (Info.Kind) {
178 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
179 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
180 case wasm::WASM_SYMBOL_TYPE_EVENT:
181 encodeULEB128(Info.ElementIndex, SubSection.getStream());
182 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
183 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
184 writeStringRef(Info.Name, SubSection.getStream());
185 break;
186 case wasm::WASM_SYMBOL_TYPE_DATA:
187 writeStringRef(Info.Name, SubSection.getStream());
188 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
189 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
190 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
191 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
193 break;
194 case wasm::WASM_SYMBOL_TYPE_SECTION:
195 encodeULEB128(Info.ElementIndex, SubSection.getStream());
196 break;
197 default:
198 llvm_unreachable("unexpected kind");
202 SubSection.done();
205 // SEGMENT_NAMES subsection
206 if (Section.SegmentInfos.size()) {
207 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
208 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
209 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
210 writeStringRef(SegmentInfo.Name, SubSection.getStream());
211 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
212 encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
214 SubSection.done();
217 // INIT_FUNCS subsection
218 if (Section.InitFunctions.size()) {
219 writeUint8(OS, wasm::WASM_INIT_FUNCS);
220 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
221 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
222 encodeULEB128(Func.Priority, SubSection.getStream());
223 encodeULEB128(Func.Symbol, SubSection.getStream());
225 SubSection.done();
228 // COMDAT_INFO subsection
229 if (Section.Comdats.size()) {
230 writeUint8(OS, wasm::WASM_COMDAT_INFO);
231 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
232 for (const auto &C : Section.Comdats) {
233 writeStringRef(C.Name, SubSection.getStream());
234 encodeULEB128(0, SubSection.getStream()); // flags for future use
235 encodeULEB128(C.Entries.size(), SubSection.getStream());
236 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
237 writeUint8(SubSection.getStream(), Entry.Kind);
238 encodeULEB128(Entry.Index, SubSection.getStream());
241 SubSection.done();
244 return 0;
247 int WasmWriter::writeSectionContent(raw_ostream &OS,
248 WasmYAML::NameSection &Section) {
249 writeStringRef(Section.Name, OS);
250 if (Section.FunctionNames.size()) {
251 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
253 SubSectionWriter SubSection(OS);
255 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
256 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
257 encodeULEB128(NameEntry.Index, SubSection.getStream());
258 writeStringRef(NameEntry.Name, SubSection.getStream());
261 SubSection.done();
263 return 0;
266 int WasmWriter::writeSectionContent(raw_ostream &OS,
267 WasmYAML::ProducersSection &Section) {
268 writeStringRef(Section.Name, OS);
269 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
270 int(!Section.SDKs.empty());
271 if (Fields == 0)
272 return 0;
273 encodeULEB128(Fields, OS);
274 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
275 std::make_pair(StringRef("processed-by"), &Section.Tools),
276 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
277 if (Field.second->empty())
278 continue;
279 writeStringRef(Field.first, OS);
280 encodeULEB128(Field.second->size(), OS);
281 for (auto &Entry : *Field.second) {
282 writeStringRef(Entry.Name, OS);
283 writeStringRef(Entry.Version, OS);
286 return 0;
289 int WasmWriter::writeSectionContent(raw_ostream &OS,
290 WasmYAML::TargetFeaturesSection &Section) {
291 writeStringRef(Section.Name, OS);
292 encodeULEB128(Section.Features.size(), OS);
293 for (auto &E : Section.Features) {
294 writeUint8(OS, E.Prefix);
295 writeStringRef(E.Name, OS);
297 return 0;
300 int WasmWriter::writeSectionContent(raw_ostream &OS,
301 WasmYAML::CustomSection &Section) {
302 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
303 if (auto Err = writeSectionContent(OS, *S))
304 return Err;
305 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
306 if (auto Err = writeSectionContent(OS, *S))
307 return Err;
308 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
309 if (auto Err = writeSectionContent(OS, *S))
310 return Err;
311 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
312 if (auto Err = writeSectionContent(OS, *S))
313 return Err;
314 } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
315 if (auto Err = writeSectionContent(OS, *S))
316 return Err;
317 } else {
318 writeStringRef(Section.Name, OS);
319 Section.Payload.writeAsBinary(OS);
321 return 0;
324 int WasmWriter::writeSectionContent(raw_ostream &OS,
325 WasmYAML::TypeSection &Section) {
326 encodeULEB128(Section.Signatures.size(), OS);
327 uint32_t ExpectedIndex = 0;
328 for (const WasmYAML::Signature &Sig : Section.Signatures) {
329 if (Sig.Index != ExpectedIndex) {
330 errs() << "Unexpected type index: " << Sig.Index << "\n";
331 return 1;
333 ++ExpectedIndex;
334 writeUint8(OS, Sig.Form);
335 encodeULEB128(Sig.ParamTypes.size(), OS);
336 for (auto ParamType : Sig.ParamTypes)
337 writeUint8(OS, ParamType);
338 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
339 encodeULEB128(0, OS);
340 } else {
341 encodeULEB128(1, OS);
342 writeUint8(OS, Sig.ReturnType);
345 return 0;
348 int WasmWriter::writeSectionContent(raw_ostream &OS,
349 WasmYAML::ImportSection &Section) {
350 encodeULEB128(Section.Imports.size(), OS);
351 for (const WasmYAML::Import &Import : Section.Imports) {
352 writeStringRef(Import.Module, OS);
353 writeStringRef(Import.Field, OS);
354 writeUint8(OS, Import.Kind);
355 switch (Import.Kind) {
356 case wasm::WASM_EXTERNAL_FUNCTION:
357 encodeULEB128(Import.SigIndex, OS);
358 NumImportedFunctions++;
359 break;
360 case wasm::WASM_EXTERNAL_GLOBAL:
361 writeUint8(OS, Import.GlobalImport.Type);
362 writeUint8(OS, Import.GlobalImport.Mutable);
363 NumImportedGlobals++;
364 break;
365 case wasm::WASM_EXTERNAL_EVENT:
366 writeUint32(OS, Import.EventImport.Attribute);
367 writeUint32(OS, Import.EventImport.SigIndex);
368 NumImportedGlobals++;
369 break;
370 case wasm::WASM_EXTERNAL_MEMORY:
371 writeLimits(Import.Memory, OS);
372 break;
373 case wasm::WASM_EXTERNAL_TABLE:
374 writeUint8(OS, Import.TableImport.ElemType);
375 writeLimits(Import.TableImport.TableLimits, OS);
376 break;
377 default:
378 errs() << "Unknown import type: " << Import.Kind << "\n";
379 return 1;
382 return 0;
385 int WasmWriter::writeSectionContent(raw_ostream &OS,
386 WasmYAML::FunctionSection &Section) {
387 encodeULEB128(Section.FunctionTypes.size(), OS);
388 for (uint32_t FuncType : Section.FunctionTypes) {
389 encodeULEB128(FuncType, OS);
391 return 0;
394 int WasmWriter::writeSectionContent(raw_ostream &OS,
395 WasmYAML::ExportSection &Section) {
396 encodeULEB128(Section.Exports.size(), OS);
397 for (const WasmYAML::Export &Export : Section.Exports) {
398 writeStringRef(Export.Name, OS);
399 writeUint8(OS, Export.Kind);
400 encodeULEB128(Export.Index, OS);
402 return 0;
405 int WasmWriter::writeSectionContent(raw_ostream &OS,
406 WasmYAML::StartSection &Section) {
407 encodeULEB128(Section.StartFunction, OS);
408 return 0;
411 int WasmWriter::writeSectionContent(raw_ostream &OS,
412 WasmYAML::TableSection &Section) {
413 encodeULEB128(Section.Tables.size(), OS);
414 for (auto &Table : Section.Tables) {
415 writeUint8(OS, Table.ElemType);
416 writeLimits(Table.TableLimits, OS);
418 return 0;
421 int WasmWriter::writeSectionContent(raw_ostream &OS,
422 WasmYAML::MemorySection &Section) {
423 encodeULEB128(Section.Memories.size(), OS);
424 for (const WasmYAML::Limits &Mem : Section.Memories) {
425 writeLimits(Mem, OS);
427 return 0;
430 int WasmWriter::writeSectionContent(raw_ostream &OS,
431 WasmYAML::GlobalSection &Section) {
432 encodeULEB128(Section.Globals.size(), OS);
433 uint32_t ExpectedIndex = NumImportedGlobals;
434 for (auto &Global : Section.Globals) {
435 if (Global.Index != ExpectedIndex) {
436 errs() << "Unexpected global index: " << Global.Index << "\n";
437 return 1;
439 ++ExpectedIndex;
440 writeUint8(OS, Global.Type);
441 writeUint8(OS, Global.Mutable);
442 writeInitExpr(Global.InitExpr, OS);
444 return 0;
447 int WasmWriter::writeSectionContent(raw_ostream &OS,
448 WasmYAML::EventSection &Section) {
449 encodeULEB128(Section.Events.size(), OS);
450 uint32_t ExpectedIndex = NumImportedEvents;
451 for (auto &Event : Section.Events) {
452 if (Event.Index != ExpectedIndex) {
453 errs() << "Unexpected event index: " << Event.Index << "\n";
454 return 1;
456 ++ExpectedIndex;
457 encodeULEB128(Event.Attribute, OS);
458 encodeULEB128(Event.SigIndex, OS);
460 return 0;
463 int WasmWriter::writeSectionContent(raw_ostream &OS,
464 WasmYAML::ElemSection &Section) {
465 encodeULEB128(Section.Segments.size(), OS);
466 for (auto &Segment : Section.Segments) {
467 encodeULEB128(Segment.TableIndex, OS);
468 writeInitExpr(Segment.Offset, OS);
470 encodeULEB128(Segment.Functions.size(), OS);
471 for (auto &Function : Segment.Functions) {
472 encodeULEB128(Function, OS);
475 return 0;
478 int WasmWriter::writeSectionContent(raw_ostream &OS,
479 WasmYAML::CodeSection &Section) {
480 encodeULEB128(Section.Functions.size(), OS);
481 uint32_t ExpectedIndex = NumImportedFunctions;
482 for (auto &Func : Section.Functions) {
483 std::string OutString;
484 raw_string_ostream StringStream(OutString);
485 if (Func.Index != ExpectedIndex) {
486 errs() << "Unexpected function index: " << Func.Index << "\n";
487 return 1;
489 ++ExpectedIndex;
491 encodeULEB128(Func.Locals.size(), StringStream);
492 for (auto &LocalDecl : Func.Locals) {
493 encodeULEB128(LocalDecl.Count, StringStream);
494 writeUint8(StringStream, LocalDecl.Type);
497 Func.Body.writeAsBinary(StringStream);
499 // Write the section size followed by the content
500 StringStream.flush();
501 encodeULEB128(OutString.size(), OS);
502 OS << OutString;
504 return 0;
507 int WasmWriter::writeSectionContent(raw_ostream &OS,
508 WasmYAML::DataSection &Section) {
509 encodeULEB128(Section.Segments.size(), OS);
510 for (auto &Segment : Section.Segments) {
511 encodeULEB128(Segment.InitFlags, OS);
512 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
513 encodeULEB128(Segment.MemoryIndex, OS);
514 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
515 writeInitExpr(Segment.Offset, OS);
516 encodeULEB128(Segment.Content.binary_size(), OS);
517 Segment.Content.writeAsBinary(OS);
519 return 0;
522 int WasmWriter::writeSectionContent(raw_ostream &OS,
523 WasmYAML::DataCountSection &Section) {
524 encodeULEB128(Section.Count, OS);
525 return 0;
528 int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
529 uint32_t SectionIndex) {
530 switch (Sec.Type) {
531 case wasm::WASM_SEC_CODE:
532 writeStringRef("reloc.CODE", OS);
533 break;
534 case wasm::WASM_SEC_DATA:
535 writeStringRef("reloc.DATA", OS);
536 break;
537 case wasm::WASM_SEC_CUSTOM: {
538 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
539 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
540 break;
542 default:
543 llvm_unreachable("not yet implemented");
544 return 1;
547 encodeULEB128(SectionIndex, OS);
548 encodeULEB128(Sec.Relocations.size(), OS);
550 for (auto Reloc : Sec.Relocations) {
551 writeUint8(OS, Reloc.Type);
552 encodeULEB128(Reloc.Offset, OS);
553 encodeULEB128(Reloc.Index, OS);
554 switch (Reloc.Type) {
555 case wasm::R_WASM_MEMORY_ADDR_LEB:
556 case wasm::R_WASM_MEMORY_ADDR_SLEB:
557 case wasm::R_WASM_MEMORY_ADDR_I32:
558 case wasm::R_WASM_FUNCTION_OFFSET_I32:
559 case wasm::R_WASM_SECTION_OFFSET_I32:
560 encodeULEB128(Reloc.Addend, OS);
563 return 0;
566 int WasmWriter::writeWasm(raw_ostream &OS) {
567 // Write headers
568 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
569 writeUint32(OS, Obj.Header.Version);
571 // Write each section
572 llvm::object::WasmSectionOrderChecker Checker;
573 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
574 StringRef SecName = "";
575 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
576 SecName = S->Name;
577 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
578 errs() << "Out of order section type: " << Sec->Type << "\n";
579 return 1;
581 encodeULEB128(Sec->Type, OS);
582 std::string OutString;
583 raw_string_ostream StringStream(OutString);
584 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
585 if (auto Err = writeSectionContent(StringStream, *S))
586 return Err;
587 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
588 if (auto Err = writeSectionContent(StringStream, *S))
589 return Err;
590 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
591 if (auto Err = writeSectionContent(StringStream, *S))
592 return Err;
593 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
594 if (auto Err = writeSectionContent(StringStream, *S))
595 return Err;
596 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
597 if (auto Err = writeSectionContent(StringStream, *S))
598 return Err;
599 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
600 if (auto Err = writeSectionContent(StringStream, *S))
601 return Err;
602 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
603 if (auto Err = writeSectionContent(StringStream, *S))
604 return Err;
605 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
606 if (auto Err = writeSectionContent(StringStream, *S))
607 return Err;
608 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
609 if (auto Err = writeSectionContent(StringStream, *S))
610 return Err;
611 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
612 if (auto Err = writeSectionContent(StringStream, *S))
613 return Err;
614 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
615 if (auto Err = writeSectionContent(StringStream, *S))
616 return Err;
617 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
618 if (auto Err = writeSectionContent(StringStream, *S))
619 return Err;
620 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
621 if (auto Err = writeSectionContent(StringStream, *S))
622 return Err;
623 } else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get())) {
624 if (auto Err = writeSectionContent(StringStream, *S))
625 return Err;
626 } else {
627 errs() << "Unknown section type: " << Sec->Type << "\n";
628 return 1;
630 StringStream.flush();
632 // Write the section size followed by the content
633 encodeULEB128(OutString.size(), OS);
634 OS << OutString;
637 // write reloc sections for any section that have relocations
638 uint32_t SectionIndex = 0;
639 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
640 if (Sec->Relocations.empty()) {
641 SectionIndex++;
642 continue;
645 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
646 std::string OutString;
647 raw_string_ostream StringStream(OutString);
648 writeRelocSection(StringStream, *Sec, SectionIndex++);
649 StringStream.flush();
651 encodeULEB128(OutString.size(), OS);
652 OS << OutString;
655 return 0;
658 namespace llvm {
659 namespace yaml {
661 int yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out) {
662 WasmWriter Writer(Doc);
664 return Writer.writeWasm(Out);
667 } // namespace yaml
668 } // namespace llvm