[ASan] Do not instrument other runtime functions with `__asan_handle_no_return`
[llvm-core.git] / tools / yaml2obj / yaml2wasm.cpp
blobdb2774a421deddae766a1d3c0d43ffae5f3af659
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/Support/Endian.h"
18 #include "llvm/Support/LEB128.h"
20 using namespace llvm;
22 /// This parses a yaml stream that represents a Wasm object file.
23 /// See docs/yaml2obj for the yaml scheema.
24 class WasmWriter {
25 public:
26 WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
27 int writeWasm(raw_ostream &OS);
29 private:
30 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
31 uint32_t SectionIndex);
33 int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
34 int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
35 int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
36 int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
37 int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
38 int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
39 int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
40 int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
41 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
42 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
43 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
44 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
45 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
47 // Custom section types
48 int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
49 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
50 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
51 int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
52 WasmYAML::Object &Obj;
53 uint32_t NumImportedFunctions = 0;
54 uint32_t NumImportedGlobals = 0;
55 uint32_t NumImportedEvents = 0;
58 static int writeUint64(raw_ostream &OS, uint64_t Value) {
59 char Data[sizeof(Value)];
60 support::endian::write64le(Data, Value);
61 OS.write(Data, sizeof(Data));
62 return 0;
65 static int writeUint32(raw_ostream &OS, uint32_t Value) {
66 char Data[sizeof(Value)];
67 support::endian::write32le(Data, Value);
68 OS.write(Data, sizeof(Data));
69 return 0;
72 static int writeUint8(raw_ostream &OS, uint8_t Value) {
73 char Data[sizeof(Value)];
74 memcpy(Data, &Value, sizeof(Data));
75 OS.write(Data, sizeof(Data));
76 return 0;
79 static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
80 encodeULEB128(Str.size(), OS);
81 OS << Str;
82 return 0;
85 static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
86 writeUint8(OS, Lim.Flags);
87 encodeULEB128(Lim.Initial, OS);
88 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
89 encodeULEB128(Lim.Maximum, OS);
90 return 0;
93 static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
94 writeUint8(OS, InitExpr.Opcode);
95 switch (InitExpr.Opcode) {
96 case wasm::WASM_OPCODE_I32_CONST:
97 encodeSLEB128(InitExpr.Value.Int32, OS);
98 break;
99 case wasm::WASM_OPCODE_I64_CONST:
100 encodeSLEB128(InitExpr.Value.Int64, OS);
101 break;
102 case wasm::WASM_OPCODE_F32_CONST:
103 writeUint32(OS, InitExpr.Value.Float32);
104 break;
105 case wasm::WASM_OPCODE_F64_CONST:
106 writeUint64(OS, InitExpr.Value.Float64);
107 break;
108 case wasm::WASM_OPCODE_GLOBAL_GET:
109 encodeULEB128(InitExpr.Value.Global, OS);
110 break;
111 default:
112 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
113 return 1;
115 writeUint8(OS, wasm::WASM_OPCODE_END);
116 return 0;
119 class SubSectionWriter {
120 raw_ostream &OS;
121 std::string OutString;
122 raw_string_ostream StringStream;
124 public:
125 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
127 void Done() {
128 StringStream.flush();
129 encodeULEB128(OutString.size(), OS);
130 OS << OutString;
131 OutString.clear();
134 raw_ostream &GetStream() { return StringStream; }
137 int WasmWriter::writeSectionContent(raw_ostream &OS,
138 WasmYAML::DylinkSection &Section) {
139 writeStringRef(Section.Name, OS);
140 encodeULEB128(Section.MemorySize, OS);
141 encodeULEB128(Section.MemoryAlignment, OS);
142 encodeULEB128(Section.TableSize, OS);
143 encodeULEB128(Section.TableAlignment, OS);
144 encodeULEB128(Section.Needed.size(), OS);
145 for (StringRef Needed : Section.Needed) {
146 writeStringRef(Needed, OS);
148 return 0;
151 int WasmWriter::writeSectionContent(raw_ostream &OS,
152 WasmYAML::LinkingSection &Section) {
153 writeStringRef(Section.Name, OS);
154 encodeULEB128(Section.Version, OS);
156 SubSectionWriter SubSection(OS);
158 // SYMBOL_TABLE subsection
159 if (Section.SymbolTable.size()) {
160 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
162 encodeULEB128(Section.SymbolTable.size(), SubSection.GetStream());
163 #ifndef NDEBUG
164 uint32_t SymbolIndex = 0;
165 #endif
166 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
167 assert(Info.Index == SymbolIndex++);
168 writeUint8(SubSection.GetStream(), Info.Kind);
169 encodeULEB128(Info.Flags, SubSection.GetStream());
170 switch (Info.Kind) {
171 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
172 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
173 case wasm::WASM_SYMBOL_TYPE_EVENT:
174 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
175 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
176 writeStringRef(Info.Name, SubSection.GetStream());
177 break;
178 case wasm::WASM_SYMBOL_TYPE_DATA:
179 writeStringRef(Info.Name, SubSection.GetStream());
180 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
181 encodeULEB128(Info.DataRef.Segment, SubSection.GetStream());
182 encodeULEB128(Info.DataRef.Offset, SubSection.GetStream());
183 encodeULEB128(Info.DataRef.Size, SubSection.GetStream());
185 break;
186 case wasm::WASM_SYMBOL_TYPE_SECTION:
187 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
188 break;
189 default:
190 llvm_unreachable("unexpected kind");
194 SubSection.Done();
197 // SEGMENT_NAMES subsection
198 if (Section.SegmentInfos.size()) {
199 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
200 encodeULEB128(Section.SegmentInfos.size(), SubSection.GetStream());
201 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
202 writeStringRef(SegmentInfo.Name, SubSection.GetStream());
203 encodeULEB128(SegmentInfo.Alignment, SubSection.GetStream());
204 encodeULEB128(SegmentInfo.Flags, SubSection.GetStream());
206 SubSection.Done();
209 // INIT_FUNCS subsection
210 if (Section.InitFunctions.size()) {
211 writeUint8(OS, wasm::WASM_INIT_FUNCS);
212 encodeULEB128(Section.InitFunctions.size(), SubSection.GetStream());
213 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
214 encodeULEB128(Func.Priority, SubSection.GetStream());
215 encodeULEB128(Func.Symbol, SubSection.GetStream());
217 SubSection.Done();
220 // COMDAT_INFO subsection
221 if (Section.Comdats.size()) {
222 writeUint8(OS, wasm::WASM_COMDAT_INFO);
223 encodeULEB128(Section.Comdats.size(), SubSection.GetStream());
224 for (const auto &C : Section.Comdats) {
225 writeStringRef(C.Name, SubSection.GetStream());
226 encodeULEB128(0, SubSection.GetStream()); // flags for future use
227 encodeULEB128(C.Entries.size(), SubSection.GetStream());
228 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
229 writeUint8(SubSection.GetStream(), Entry.Kind);
230 encodeULEB128(Entry.Index, SubSection.GetStream());
233 SubSection.Done();
236 return 0;
239 int WasmWriter::writeSectionContent(raw_ostream &OS,
240 WasmYAML::NameSection &Section) {
241 writeStringRef(Section.Name, OS);
242 if (Section.FunctionNames.size()) {
243 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
245 SubSectionWriter SubSection(OS);
247 encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
248 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
249 encodeULEB128(NameEntry.Index, SubSection.GetStream());
250 writeStringRef(NameEntry.Name, SubSection.GetStream());
253 SubSection.Done();
255 return 0;
258 int WasmWriter::writeSectionContent(raw_ostream &OS,
259 WasmYAML::ProducersSection &Section) {
260 writeStringRef(Section.Name, OS);
261 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
262 int(!Section.SDKs.empty());
263 if (Fields == 0)
264 return 0;
265 encodeULEB128(Fields, OS);
266 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
267 std::make_pair(StringRef("processed-by"), &Section.Tools),
268 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
269 if (Field.second->empty())
270 continue;
271 writeStringRef(Field.first, OS);
272 encodeULEB128(Field.second->size(), OS);
273 for (auto &Entry : *Field.second) {
274 writeStringRef(Entry.Name, OS);
275 writeStringRef(Entry.Version, OS);
278 return 0;
281 int WasmWriter::writeSectionContent(raw_ostream &OS,
282 WasmYAML::CustomSection &Section) {
283 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
284 if (auto Err = writeSectionContent(OS, *S))
285 return Err;
286 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
287 if (auto Err = writeSectionContent(OS, *S))
288 return Err;
289 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
290 if (auto Err = writeSectionContent(OS, *S))
291 return Err;
292 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
293 if (auto Err = writeSectionContent(OS, *S))
294 return Err;
295 } else {
296 writeStringRef(Section.Name, OS);
297 Section.Payload.writeAsBinary(OS);
299 return 0;
302 int WasmWriter::writeSectionContent(raw_ostream &OS,
303 WasmYAML::TypeSection &Section) {
304 encodeULEB128(Section.Signatures.size(), OS);
305 uint32_t ExpectedIndex = 0;
306 for (const WasmYAML::Signature &Sig : Section.Signatures) {
307 if (Sig.Index != ExpectedIndex) {
308 errs() << "Unexpected type index: " << Sig.Index << "\n";
309 return 1;
311 ++ExpectedIndex;
312 writeUint8(OS, Sig.Form);
313 encodeULEB128(Sig.ParamTypes.size(), OS);
314 for (auto ParamType : Sig.ParamTypes)
315 writeUint8(OS, ParamType);
316 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
317 encodeULEB128(0, OS);
318 } else {
319 encodeULEB128(1, OS);
320 writeUint8(OS, Sig.ReturnType);
323 return 0;
326 int WasmWriter::writeSectionContent(raw_ostream &OS,
327 WasmYAML::ImportSection &Section) {
328 encodeULEB128(Section.Imports.size(), OS);
329 for (const WasmYAML::Import &Import : Section.Imports) {
330 writeStringRef(Import.Module, OS);
331 writeStringRef(Import.Field, OS);
332 writeUint8(OS, Import.Kind);
333 switch (Import.Kind) {
334 case wasm::WASM_EXTERNAL_FUNCTION:
335 encodeULEB128(Import.SigIndex, OS);
336 NumImportedFunctions++;
337 break;
338 case wasm::WASM_EXTERNAL_GLOBAL:
339 writeUint8(OS, Import.GlobalImport.Type);
340 writeUint8(OS, Import.GlobalImport.Mutable);
341 NumImportedGlobals++;
342 break;
343 case wasm::WASM_EXTERNAL_EVENT:
344 writeUint32(OS, Import.EventImport.Attribute);
345 writeUint32(OS, Import.EventImport.SigIndex);
346 NumImportedGlobals++;
347 break;
348 case wasm::WASM_EXTERNAL_MEMORY:
349 writeLimits(Import.Memory, OS);
350 break;
351 case wasm::WASM_EXTERNAL_TABLE:
352 writeUint8(OS, Import.TableImport.ElemType);
353 writeLimits(Import.TableImport.TableLimits, OS);
354 break;
355 default:
356 errs() << "Unknown import type: " << Import.Kind << "\n";
357 return 1;
360 return 0;
363 int WasmWriter::writeSectionContent(raw_ostream &OS,
364 WasmYAML::FunctionSection &Section) {
365 encodeULEB128(Section.FunctionTypes.size(), OS);
366 for (uint32_t FuncType : Section.FunctionTypes) {
367 encodeULEB128(FuncType, OS);
369 return 0;
372 int WasmWriter::writeSectionContent(raw_ostream &OS,
373 WasmYAML::ExportSection &Section) {
374 encodeULEB128(Section.Exports.size(), OS);
375 for (const WasmYAML::Export &Export : Section.Exports) {
376 writeStringRef(Export.Name, OS);
377 writeUint8(OS, Export.Kind);
378 encodeULEB128(Export.Index, OS);
380 return 0;
383 int WasmWriter::writeSectionContent(raw_ostream &OS,
384 WasmYAML::StartSection &Section) {
385 encodeULEB128(Section.StartFunction, OS);
386 return 0;
389 int WasmWriter::writeSectionContent(raw_ostream &OS,
390 WasmYAML::TableSection &Section) {
391 encodeULEB128(Section.Tables.size(), OS);
392 for (auto &Table : Section.Tables) {
393 writeUint8(OS, Table.ElemType);
394 writeLimits(Table.TableLimits, OS);
396 return 0;
399 int WasmWriter::writeSectionContent(raw_ostream &OS,
400 WasmYAML::MemorySection &Section) {
401 encodeULEB128(Section.Memories.size(), OS);
402 for (const WasmYAML::Limits &Mem : Section.Memories) {
403 writeLimits(Mem, OS);
405 return 0;
408 int WasmWriter::writeSectionContent(raw_ostream &OS,
409 WasmYAML::GlobalSection &Section) {
410 encodeULEB128(Section.Globals.size(), OS);
411 uint32_t ExpectedIndex = NumImportedGlobals;
412 for (auto &Global : Section.Globals) {
413 if (Global.Index != ExpectedIndex) {
414 errs() << "Unexpected global index: " << Global.Index << "\n";
415 return 1;
417 ++ExpectedIndex;
418 writeUint8(OS, Global.Type);
419 writeUint8(OS, Global.Mutable);
420 writeInitExpr(Global.InitExpr, OS);
422 return 0;
425 int WasmWriter::writeSectionContent(raw_ostream &OS,
426 WasmYAML::EventSection &Section) {
427 encodeULEB128(Section.Events.size(), OS);
428 uint32_t ExpectedIndex = NumImportedEvents;
429 for (auto &Event : Section.Events) {
430 if (Event.Index != ExpectedIndex) {
431 errs() << "Unexpected event index: " << Event.Index << "\n";
432 return 1;
434 ++ExpectedIndex;
435 encodeULEB128(Event.Attribute, OS);
436 encodeULEB128(Event.SigIndex, OS);
438 return 0;
441 int WasmWriter::writeSectionContent(raw_ostream &OS,
442 WasmYAML::ElemSection &Section) {
443 encodeULEB128(Section.Segments.size(), OS);
444 for (auto &Segment : Section.Segments) {
445 encodeULEB128(Segment.TableIndex, OS);
446 writeInitExpr(Segment.Offset, OS);
448 encodeULEB128(Segment.Functions.size(), OS);
449 for (auto &Function : Segment.Functions) {
450 encodeULEB128(Function, OS);
453 return 0;
456 int WasmWriter::writeSectionContent(raw_ostream &OS,
457 WasmYAML::CodeSection &Section) {
458 encodeULEB128(Section.Functions.size(), OS);
459 uint32_t ExpectedIndex = NumImportedFunctions;
460 for (auto &Func : Section.Functions) {
461 std::string OutString;
462 raw_string_ostream StringStream(OutString);
463 if (Func.Index != ExpectedIndex) {
464 errs() << "Unexpected function index: " << Func.Index << "\n";
465 return 1;
467 ++ExpectedIndex;
469 encodeULEB128(Func.Locals.size(), StringStream);
470 for (auto &LocalDecl : Func.Locals) {
471 encodeULEB128(LocalDecl.Count, StringStream);
472 writeUint8(StringStream, LocalDecl.Type);
475 Func.Body.writeAsBinary(StringStream);
477 // Write the section size followed by the content
478 StringStream.flush();
479 encodeULEB128(OutString.size(), OS);
480 OS << OutString;
482 return 0;
485 int WasmWriter::writeSectionContent(raw_ostream &OS,
486 WasmYAML::DataSection &Section) {
487 encodeULEB128(Section.Segments.size(), OS);
488 for (auto &Segment : Section.Segments) {
489 encodeULEB128(Segment.MemoryIndex, OS);
490 writeInitExpr(Segment.Offset, OS);
491 encodeULEB128(Segment.Content.binary_size(), OS);
492 Segment.Content.writeAsBinary(OS);
494 return 0;
497 int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
498 uint32_t SectionIndex) {
499 switch (Sec.Type) {
500 case wasm::WASM_SEC_CODE:
501 writeStringRef("reloc.CODE", OS);
502 break;
503 case wasm::WASM_SEC_DATA:
504 writeStringRef("reloc.DATA", OS);
505 break;
506 case wasm::WASM_SEC_CUSTOM: {
507 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
508 if (!CustomSection->Name.startswith(".debug_")) {
509 llvm_unreachable("not yet implemented (only for debug sections)");
510 return 1;
513 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
514 break;
516 default:
517 llvm_unreachable("not yet implemented");
518 return 1;
521 encodeULEB128(SectionIndex, OS);
522 encodeULEB128(Sec.Relocations.size(), OS);
524 for (auto Reloc : Sec.Relocations) {
525 writeUint8(OS, Reloc.Type);
526 encodeULEB128(Reloc.Offset, OS);
527 encodeULEB128(Reloc.Index, OS);
528 switch (Reloc.Type) {
529 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
530 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
531 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
532 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
533 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
534 encodeULEB128(Reloc.Addend, OS);
537 return 0;
540 int WasmWriter::writeWasm(raw_ostream &OS) {
541 // Write headers
542 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
543 writeUint32(OS, Obj.Header.Version);
545 // Write each section
546 llvm::object::WasmSectionOrderChecker Checker;
547 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
548 StringRef SecName = "";
549 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
550 SecName = S->Name;
551 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
552 errs() << "Out of order section type: " << Sec->Type << "\n";
553 return 1;
555 encodeULEB128(Sec->Type, OS);
556 std::string OutString;
557 raw_string_ostream StringStream(OutString);
558 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
559 if (auto Err = writeSectionContent(StringStream, *S))
560 return Err;
561 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
562 if (auto Err = writeSectionContent(StringStream, *S))
563 return Err;
564 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
565 if (auto Err = writeSectionContent(StringStream, *S))
566 return Err;
567 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
568 if (auto Err = writeSectionContent(StringStream, *S))
569 return Err;
570 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
571 if (auto Err = writeSectionContent(StringStream, *S))
572 return Err;
573 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
574 if (auto Err = writeSectionContent(StringStream, *S))
575 return Err;
576 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
577 if (auto Err = writeSectionContent(StringStream, *S))
578 return Err;
579 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
580 if (auto Err = writeSectionContent(StringStream, *S))
581 return Err;
582 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
583 if (auto Err = writeSectionContent(StringStream, *S))
584 return Err;
585 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
586 if (auto Err = writeSectionContent(StringStream, *S))
587 return Err;
588 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
589 if (auto Err = writeSectionContent(StringStream, *S))
590 return Err;
591 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
592 if (auto Err = writeSectionContent(StringStream, *S))
593 return Err;
594 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
595 if (auto Err = writeSectionContent(StringStream, *S))
596 return Err;
597 } else {
598 errs() << "Unknown section type: " << Sec->Type << "\n";
599 return 1;
601 StringStream.flush();
603 // Write the section size followed by the content
604 encodeULEB128(OutString.size(), OS);
605 OS << OutString;
608 // write reloc sections for any section that have relocations
609 uint32_t SectionIndex = 0;
610 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
611 if (Sec->Relocations.empty()) {
612 SectionIndex++;
613 continue;
616 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
617 std::string OutString;
618 raw_string_ostream StringStream(OutString);
619 writeRelocSection(StringStream, *Sec, SectionIndex++);
620 StringStream.flush();
622 encodeULEB128(OutString.size(), OS);
623 OS << OutString;
626 return 0;
629 int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
630 WasmWriter Writer(Doc);
632 return Writer.writeWasm(Out);