LLVM 20.0.0git
WasmEmitter.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
13//
14
15#include "llvm/Object/Wasm.h"
18#include "llvm/Support/Endian.h"
19#include "llvm/Support/LEB128.h"
20
21using namespace llvm;
22
23namespace {
24/// This parses a yaml stream that represents a Wasm object file.
25/// See docs/yaml2obj for the yaml scheema.
26class WasmWriter {
27public:
28 WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)
29 : Obj(Obj), ErrHandler(EH) {}
30 bool writeWasm(raw_ostream &OS);
31
32private:
33 void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
34 uint32_t SectionIndex);
35
36 void writeInitExpr(raw_ostream &OS, const WasmYAML::InitExpr &InitExpr);
37
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::TagSection &Section);
45 void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &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);
52
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,
61 uint32_t NumImportedFunctions = 0;
62 uint32_t NumImportedGlobals = 0;
63 uint32_t NumImportedTables = 0;
64 uint32_t NumImportedTags = 0;
65
66 bool HasError = false;
67 yaml::ErrorHandler ErrHandler;
68 void reportError(const Twine &Msg);
69};
70
71class SubSectionWriter {
73 std::string OutString;
74 raw_string_ostream StringStream;
75
76public:
77 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
78
79 void done() {
80 StringStream.flush();
81 encodeULEB128(OutString.size(), OS);
82 OS << OutString;
83 OutString.clear();
84 }
85
86 raw_ostream &getStream() { return StringStream; }
87};
88
89} // end anonymous namespace
90
92 char Data[sizeof(Value)];
94 OS.write(Data, sizeof(Data));
95 return 0;
96}
97
99 char Data[sizeof(Value)];
101 OS.write(Data, sizeof(Data));
102 return 0;
103}
104
106 char Data[sizeof(Value)];
107 memcpy(Data, &Value, sizeof(Data));
108 OS.write(Data, sizeof(Data));
109 return 0;
110}
111
112static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
113 encodeULEB128(Str.size(), OS);
114 OS << Str;
115 return 0;
116}
117
118static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
119 writeUint8(OS, Lim.Flags);
123 return 0;
124}
125
126void WasmWriter::reportError(const Twine &Msg) {
127 ErrHandler(Msg);
128 HasError = true;
129}
130
131void WasmWriter::writeInitExpr(raw_ostream &OS,
132 const WasmYAML::InitExpr &InitExpr) {
133 if (InitExpr.Extended) {
134 InitExpr.Body.writeAsBinary(OS);
135 } else {
136 writeUint8(OS, InitExpr.Inst.Opcode);
137 switch (InitExpr.Inst.Opcode) {
139 encodeSLEB128(InitExpr.Inst.Value.Int32, OS);
140 break;
142 encodeSLEB128(InitExpr.Inst.Value.Int64, OS);
143 break;
145 writeUint32(OS, InitExpr.Inst.Value.Float32);
146 break;
148 writeUint64(OS, InitExpr.Inst.Value.Float64);
149 break;
151 encodeULEB128(InitExpr.Inst.Value.Global, OS);
152 break;
153 default:
154 reportError("unknown opcode in init_expr: " +
155 Twine(InitExpr.Inst.Opcode));
156 return;
157 }
159 }
160}
161
162void WasmWriter::writeSectionContent(raw_ostream &OS,
163 WasmYAML::DylinkSection &Section) {
165
167 SubSectionWriter SubSection(OS);
168 raw_ostream &SubOS = SubSection.getStream();
169 encodeULEB128(Section.MemorySize, SubOS);
170 encodeULEB128(Section.MemoryAlignment, SubOS);
171 encodeULEB128(Section.TableSize, SubOS);
172 encodeULEB128(Section.TableAlignment, SubOS);
173 SubSection.done();
174
175 if (Section.Needed.size()) {
177 raw_ostream &SubOS = SubSection.getStream();
178 encodeULEB128(Section.Needed.size(), SubOS);
179 for (StringRef Needed : Section.Needed)
180 writeStringRef(Needed, SubOS);
181 SubSection.done();
182 }
183}
184
185void WasmWriter::writeSectionContent(raw_ostream &OS,
186 WasmYAML::LinkingSection &Section) {
188 encodeULEB128(Section.Version, OS);
189
190 SubSectionWriter SubSection(OS);
191
192 // SYMBOL_TABLE subsection
193 if (Section.SymbolTable.size()) {
195 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
196 for (auto Sym : llvm::enumerate(Section.SymbolTable)) {
197 const WasmYAML::SymbolInfo &Info = Sym.value();
198 assert(Info.Index == Sym.index());
199 writeUint8(SubSection.getStream(), Info.Kind);
200 encodeULEB128(Info.Flags, SubSection.getStream());
201 switch (Info.Kind) {
206 encodeULEB128(Info.ElementIndex, SubSection.getStream());
207 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
209 writeStringRef(Info.Name, SubSection.getStream());
210 break;
212 writeStringRef(Info.Name, SubSection.getStream());
213 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
214 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
215 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
216 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
217 }
218 break;
220 encodeULEB128(Info.ElementIndex, SubSection.getStream());
221 break;
222 default:
223 llvm_unreachable("unexpected kind");
224 }
225 }
226
227 SubSection.done();
228 }
229
230 // SEGMENT_NAMES subsection
231 if (Section.SegmentInfos.size()) {
233 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
234 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
235 writeStringRef(SegmentInfo.Name, SubSection.getStream());
236 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
237 encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
238 }
239 SubSection.done();
240 }
241
242 // INIT_FUNCS subsection
243 if (Section.InitFunctions.size()) {
245 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
246 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
247 encodeULEB128(Func.Priority, SubSection.getStream());
248 encodeULEB128(Func.Symbol, SubSection.getStream());
249 }
250 SubSection.done();
251 }
252
253 // COMDAT_INFO subsection
254 if (Section.Comdats.size()) {
256 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
257 for (const auto &C : Section.Comdats) {
258 writeStringRef(C.Name, SubSection.getStream());
259 encodeULEB128(0, SubSection.getStream()); // flags for future use
260 encodeULEB128(C.Entries.size(), SubSection.getStream());
261 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
262 writeUint8(SubSection.getStream(), Entry.Kind);
263 encodeULEB128(Entry.Index, SubSection.getStream());
264 }
265 }
266 SubSection.done();
267 }
268}
269
270void WasmWriter::writeSectionContent(raw_ostream &OS,
271 WasmYAML::NameSection &Section) {
273 if (Section.FunctionNames.size()) {
275
276 SubSectionWriter SubSection(OS);
277
278 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
279 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
280 encodeULEB128(NameEntry.Index, SubSection.getStream());
281 writeStringRef(NameEntry.Name, SubSection.getStream());
282 }
283
284 SubSection.done();
285 }
286 if (Section.GlobalNames.size()) {
288
289 SubSectionWriter SubSection(OS);
290
291 encodeULEB128(Section.GlobalNames.size(), SubSection.getStream());
292 for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {
293 encodeULEB128(NameEntry.Index, SubSection.getStream());
294 writeStringRef(NameEntry.Name, SubSection.getStream());
295 }
296
297 SubSection.done();
298 }
299 if (Section.DataSegmentNames.size()) {
301
302 SubSectionWriter SubSection(OS);
303
304 encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());
305 for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {
306 encodeULEB128(NameEntry.Index, SubSection.getStream());
307 writeStringRef(NameEntry.Name, SubSection.getStream());
308 }
309
310 SubSection.done();
311 }
312}
313
314void WasmWriter::writeSectionContent(raw_ostream &OS,
317 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
318 int(!Section.SDKs.empty());
319 if (Fields == 0)
320 return;
321 encodeULEB128(Fields, OS);
322 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
323 std::make_pair(StringRef("processed-by"), &Section.Tools),
324 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
325 if (Field.second->empty())
326 continue;
327 writeStringRef(Field.first, OS);
328 encodeULEB128(Field.second->size(), OS);
329 for (auto &Entry : *Field.second) {
330 writeStringRef(Entry.Name, OS);
331 writeStringRef(Entry.Version, OS);
332 }
333 }
334}
335
336void WasmWriter::writeSectionContent(raw_ostream &OS,
339 encodeULEB128(Section.Features.size(), OS);
340 for (auto &E : Section.Features) {
341 writeUint8(OS, E.Prefix);
342 writeStringRef(E.Name, OS);
343 }
344}
345
346void WasmWriter::writeSectionContent(raw_ostream &OS,
347 WasmYAML::CustomSection &Section) {
348 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
349 writeSectionContent(OS, *S);
350 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
351 writeSectionContent(OS, *S);
352 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
353 writeSectionContent(OS, *S);
354 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
355 writeSectionContent(OS, *S);
356 } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
357 writeSectionContent(OS, *S);
358 } else {
360 Section.Payload.writeAsBinary(OS);
361 }
362}
363
364void WasmWriter::writeSectionContent(raw_ostream &OS,
365 WasmYAML::TypeSection &Section) {
366 encodeULEB128(Section.Signatures.size(), OS);
367 uint32_t ExpectedIndex = 0;
368 for (const WasmYAML::Signature &Sig : Section.Signatures) {
369 if (Sig.Index != ExpectedIndex) {
370 reportError("unexpected type index: " + Twine(Sig.Index));
371 return;
372 }
373 ++ExpectedIndex;
374 writeUint8(OS, Sig.Form);
375 encodeULEB128(Sig.ParamTypes.size(), OS);
376 for (auto ParamType : Sig.ParamTypes)
377 writeUint8(OS, ParamType);
378 encodeULEB128(Sig.ReturnTypes.size(), OS);
379 for (auto ReturnType : Sig.ReturnTypes)
380 writeUint8(OS, ReturnType);
381 }
382}
383
384void WasmWriter::writeSectionContent(raw_ostream &OS,
385 WasmYAML::ImportSection &Section) {
386 encodeULEB128(Section.Imports.size(), OS);
387 for (const WasmYAML::Import &Import : Section.Imports) {
388 writeStringRef(Import.Module, OS);
389 writeStringRef(Import.Field, OS);
390 writeUint8(OS, Import.Kind);
391 switch (Import.Kind) {
393 encodeULEB128(Import.SigIndex, OS);
394 NumImportedFunctions++;
395 break;
397 writeUint8(OS, Import.GlobalImport.Type);
398 writeUint8(OS, Import.GlobalImport.Mutable);
399 NumImportedGlobals++;
400 break;
402 writeUint8(OS, 0); // Reserved 'attribute' field
403 encodeULEB128(Import.SigIndex, OS);
404 NumImportedTags++;
405 break;
407 writeLimits(Import.Memory, OS);
408 break;
410 writeUint8(OS, Import.TableImport.ElemType);
411 writeLimits(Import.TableImport.TableLimits, OS);
412 NumImportedTables++;
413 break;
414 default:
415 reportError("unknown import type: " +Twine(Import.Kind));
416 return;
417 }
418 }
419}
420
421void WasmWriter::writeSectionContent(raw_ostream &OS,
422 WasmYAML::FunctionSection &Section) {
423 encodeULEB128(Section.FunctionTypes.size(), OS);
424 for (uint32_t FuncType : Section.FunctionTypes)
425 encodeULEB128(FuncType, OS);
426}
427
428void WasmWriter::writeSectionContent(raw_ostream &OS,
429 WasmYAML::ExportSection &Section) {
430 encodeULEB128(Section.Exports.size(), OS);
431 for (const WasmYAML::Export &Export : Section.Exports) {
432 writeStringRef(Export.Name, OS);
433 writeUint8(OS, Export.Kind);
434 encodeULEB128(Export.Index, OS);
435 }
436}
437
438void WasmWriter::writeSectionContent(raw_ostream &OS,
439 WasmYAML::StartSection &Section) {
440 encodeULEB128(Section.StartFunction, OS);
441}
442
443void WasmWriter::writeSectionContent(raw_ostream &OS,
444 WasmYAML::TableSection &Section) {
445 encodeULEB128(Section.Tables.size(), OS);
446 uint32_t ExpectedIndex = NumImportedTables;
447 for (auto &Table : Section.Tables) {
448 if (Table.Index != ExpectedIndex) {
449 reportError("unexpected table index: " + Twine(Table.Index));
450 return;
451 }
452 ++ExpectedIndex;
453 writeUint8(OS, Table.ElemType);
454 writeLimits(Table.TableLimits, OS);
455 }
456}
457
458void WasmWriter::writeSectionContent(raw_ostream &OS,
459 WasmYAML::MemorySection &Section) {
460 encodeULEB128(Section.Memories.size(), OS);
461 for (const WasmYAML::Limits &Mem : Section.Memories)
462 writeLimits(Mem, OS);
463}
464
465void WasmWriter::writeSectionContent(raw_ostream &OS,
466 WasmYAML::TagSection &Section) {
467 encodeULEB128(Section.TagTypes.size(), OS);
468 for (uint32_t TagType : Section.TagTypes) {
469 writeUint8(OS, 0); // Reserved 'attribute' field
470 encodeULEB128(TagType, OS);
471 }
472}
473
474void WasmWriter::writeSectionContent(raw_ostream &OS,
475 WasmYAML::GlobalSection &Section) {
476 encodeULEB128(Section.Globals.size(), OS);
477 uint32_t ExpectedIndex = NumImportedGlobals;
478 for (auto &Global : Section.Globals) {
479 if (Global.Index != ExpectedIndex) {
480 reportError("unexpected global index: " + Twine(Global.Index));
481 return;
482 }
483 ++ExpectedIndex;
484 writeUint8(OS, Global.Type);
485 writeUint8(OS, Global.Mutable);
486 writeInitExpr(OS, Global.Init);
487 }
488}
489
490void WasmWriter::writeSectionContent(raw_ostream &OS,
491 WasmYAML::ElemSection &Section) {
492 encodeULEB128(Section.Segments.size(), OS);
493 for (auto &Segment : Section.Segments) {
494 encodeULEB128(Segment.Flags, OS);
496 encodeULEB128(Segment.TableNumber, OS);
497
498 writeInitExpr(OS, Segment.Offset);
499
500 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
501 // We only support active function table initializers, for which the elem
502 // kind is specified to be written as 0x00 and interpreted to mean
503 // "funcref".
504 if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {
505 reportError("unexpected elemkind: " + Twine(Segment.ElemKind));
506 return;
507 }
508 const uint8_t ElemKind = 0;
509 writeUint8(OS, ElemKind);
510 }
511
512 encodeULEB128(Segment.Functions.size(), OS);
513 for (auto &Function : Segment.Functions)
515 }
516}
517
518void WasmWriter::writeSectionContent(raw_ostream &OS,
519 WasmYAML::CodeSection &Section) {
520 encodeULEB128(Section.Functions.size(), OS);
521 uint32_t ExpectedIndex = NumImportedFunctions;
522 for (auto &Func : Section.Functions) {
523 std::string OutString;
524 raw_string_ostream StringStream(OutString);
525 if (Func.Index != ExpectedIndex) {
526 reportError("unexpected function index: " + Twine(Func.Index));
527 return;
528 }
529 ++ExpectedIndex;
530
531 encodeULEB128(Func.Locals.size(), StringStream);
532 for (auto &LocalDecl : Func.Locals) {
533 encodeULEB128(LocalDecl.Count, StringStream);
534 writeUint8(StringStream, LocalDecl.Type);
535 }
536
537 Func.Body.writeAsBinary(StringStream);
538
539 // Write the section size followed by the content
540 StringStream.flush();
541 encodeULEB128(OutString.size(), OS);
542 OS << OutString;
543 }
544}
545
546void WasmWriter::writeSectionContent(raw_ostream &OS,
547 WasmYAML::DataSection &Section) {
548 encodeULEB128(Section.Segments.size(), OS);
549 for (auto &Segment : Section.Segments) {
550 encodeULEB128(Segment.InitFlags, OS);
551 if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
552 encodeULEB128(Segment.MemoryIndex, OS);
553 if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)
554 writeInitExpr(OS, Segment.Offset);
555 encodeULEB128(Segment.Content.binary_size(), OS);
556 Segment.Content.writeAsBinary(OS);
557 }
558}
559
560void WasmWriter::writeSectionContent(raw_ostream &OS,
562 encodeULEB128(Section.Count, OS);
563}
564
565void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
566 uint32_t SectionIndex) {
567 switch (Sec.Type) {
569 writeStringRef("reloc.CODE", OS);
570 break;
572 writeStringRef("reloc.DATA", OS);
573 break;
575 auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
576 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
577 break;
578 }
579 default:
580 llvm_unreachable("not yet implemented");
581 }
582
583 encodeULEB128(SectionIndex, OS);
584 encodeULEB128(Sec.Relocations.size(), OS);
585
586 for (auto Reloc : Sec.Relocations) {
587 writeUint8(OS, Reloc.Type);
588 encodeULEB128(Reloc.Offset, OS);
589 encodeULEB128(Reloc.Index, OS);
590 if (wasm::relocTypeHasAddend(Reloc.Type))
591 encodeSLEB128(Reloc.Addend, OS);
592 }
593}
594
595bool WasmWriter::writeWasm(raw_ostream &OS) {
596 // Write headers
598 writeUint32(OS, Obj.Header.Version);
599
600 // Write each section
602 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
603 StringRef SecName = "";
604 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
605 SecName = S->Name;
606 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
607 reportError("out of order section type: " +
608 wasm::sectionTypeToString(Sec->Type));
609 return false;
610 }
611 encodeULEB128(Sec->Type, OS);
612 std::string OutString;
613 raw_string_ostream StringStream(OutString);
614 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
615 writeSectionContent(StringStream, *S);
616 else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
617 writeSectionContent(StringStream, *S);
618 else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
619 writeSectionContent(StringStream, *S);
620 else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
621 writeSectionContent(StringStream, *S);
622 else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
623 writeSectionContent(StringStream, *S);
624 else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
625 writeSectionContent(StringStream, *S);
626 else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))
627 writeSectionContent(StringStream, *S);
628 else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
629 writeSectionContent(StringStream, *S);
630 else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
631 writeSectionContent(StringStream, *S);
632 else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
633 writeSectionContent(StringStream, *S);
634 else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
635 writeSectionContent(StringStream, *S);
636 else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
637 writeSectionContent(StringStream, *S);
638 else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
639 writeSectionContent(StringStream, *S);
640 else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
641 writeSectionContent(StringStream, *S);
642 else
643 reportError("unknown section type: " + Twine(Sec->Type));
644
645 if (HasError)
646 return false;
647
648 StringStream.flush();
649
650 unsigned HeaderSecSizeEncodingLen =
651 Sec->HeaderSecSizeEncodingLen.value_or(5);
652 unsigned RequiredLen = getULEB128Size(OutString.size());
653 // Wasm spec does not allow LEBs larger than 5 bytes
654 assert(RequiredLen <= 5);
655 if (HeaderSecSizeEncodingLen < RequiredLen) {
656 reportError("section header length can't be encoded in a LEB of size " +
657 Twine(HeaderSecSizeEncodingLen));
658 return false;
659 }
660 // Write the section size followed by the content
661 encodeULEB128(OutString.size(), OS, HeaderSecSizeEncodingLen);
662 OS << OutString;
663 }
664
665 // write reloc sections for any section that have relocations
666 uint32_t SectionIndex = 0;
667 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
668 if (Sec->Relocations.empty()) {
669 SectionIndex++;
670 continue;
671 }
672
674 std::string OutString;
675 raw_string_ostream StringStream(OutString);
676 writeRelocSection(StringStream, *Sec, SectionIndex++);
677 StringStream.flush();
678
679 encodeULEB128(OutString.size(), OS);
680 OS << OutString;
681 }
682
683 return true;
684}
685
686namespace llvm {
687namespace yaml {
688
690 WasmWriter Writer(Doc, EH);
691 return Writer.writeWasm(Out);
692}
693
694} // namespace yaml
695} // namespace llvm
static Error reportError(StringRef Message)
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Symbol * Sym
Definition: ELF_riscv.cpp:479
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static int writeUint32(raw_ostream &OS, uint32_t Value)
Definition: WasmEmitter.cpp:98
static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS)
static int writeStringRef(const StringRef &Str, raw_ostream &OS)
static int writeUint8(raw_ostream &OS, uint8_t Value)
static int writeUint64(raw_ostream &OS, uint64_t Value)
Definition: WasmEmitter.cpp:91
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
LLVM Value Representation.
Definition: Value.h:74
An efficient, type-erasing, non-owning reference to a callable.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:661
void writeAsBinary(raw_ostream &OS, uint64_t N=UINT64_MAX) const
Write the contents (regardless of whether it is binary or a hex string) as binary to the given raw_os...
Definition: YAML.cpp:39
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Entry
Definition: COFF.h:844
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
NodeAddr< FuncNode * > Func
Definition: RDFGraph.h:393
void write64le(void *P, uint64_t V)
Definition: Endian.h:471
void write32le(void *P, uint32_t V)
Definition: Endian.h:468
@ WASM_OPCODE_F64_CONST
Definition: Wasm.h:105
@ WASM_OPCODE_END
Definition: Wasm.h:93
@ WASM_OPCODE_F32_CONST
Definition: Wasm.h:104
@ WASM_OPCODE_GLOBAL_GET
Definition: Wasm.h:98
@ WASM_OPCODE_I64_CONST
Definition: Wasm.h:103
@ WASM_OPCODE_I32_CONST
Definition: Wasm.h:102
const unsigned WASM_SYMBOL_UNDEFINED
Definition: Wasm.h:243
const char WasmMagic[]
Definition: Wasm.h:26
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition: Wasm.h:170
@ WASM_EXTERNAL_TABLE
Definition: Wasm.h:85
@ WASM_EXTERNAL_FUNCTION
Definition: Wasm.h:84
@ WASM_EXTERNAL_TAG
Definition: Wasm.h:88
@ WASM_EXTERNAL_MEMORY
Definition: Wasm.h:86
@ WASM_EXTERNAL_GLOBAL
Definition: Wasm.h:87
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
Definition: Wasm.h:173
@ WASM_NAMES_DATA_SEGMENT
Definition: Wasm.h:187
@ WASM_NAMES_GLOBAL
Definition: Wasm.h:186
@ WASM_NAMES_FUNCTION
Definition: Wasm.h:184
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:218
@ WASM_SYMBOL_TYPE_DATA
Definition: Wasm.h:217
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:220
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:221
@ WASM_SYMBOL_TYPE_SECTION
Definition: Wasm.h:219
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:216
@ WASM_SEC_CODE
Definition: Wasm.h:45
@ WASM_SEC_CUSTOM
Definition: Wasm.h:35
@ WASM_SEC_DATA
Definition: Wasm.h:46
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:157
bool relocTypeHasAddend(uint32_t type)
Definition: Wasm.cpp:66
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition: Wasm.h:163
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition: Wasm.h:164
llvm::StringRef sectionTypeToString(uint32_t type)
Definition: Wasm.cpp:41
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition: Wasm.h:245
@ WASM_DYLINK_NEEDED
Definition: Wasm.h:201
@ WASM_DYLINK_MEM_INFO
Definition: Wasm.h:200
@ WASM_INIT_FUNCS
Definition: Wasm.h:193
@ WASM_COMDAT_INFO
Definition: Wasm.h:194
@ WASM_SEGMENT_INFO
Definition: Wasm.h:192
@ WASM_SYMBOL_TABLE
Definition: Wasm.h:195
bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition: STLExtras.h:2448
@ Export
Export information to summary.
@ Import
Import information from summary.
@ Global
Append to llvm.global_dtors.
unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
Definition: LEB128.cpp:19
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
Definition: LEB128.h:23
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition: LEB128.h:80
wasm::WasmInitExprMVP Inst
Definition: WasmYAML.h:69
yaml::BinaryRef Body
Definition: WasmYAML.h:70
yaml::Hex32 Minimum
Definition: WasmYAML.h:49
LimitFlags Flags
Definition: WasmYAML.h:48
yaml::Hex32 Maximum
Definition: WasmYAML.h:50
std::vector< Relocation > Relocations
Definition: WasmYAML.h:191
SignatureForm Form
Definition: WasmYAML.h:155
std::vector< ValueType > ReturnTypes
Definition: WasmYAML.h:157
std::vector< ValueType > ParamTypes
Definition: WasmYAML.h:156
union llvm::wasm::WasmInitExprMVP::@187 Value
Common declarations for yaml2obj.