LLVM 24.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,
59 WasmYAML::TargetFeaturesSection &Section);
60 WasmYAML::Object &Obj;
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 {
72 raw_ostream &OS;
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 encodeULEB128(OutString.size(), OS);
81 OS << OutString;
82 OutString.clear();
83 }
84
85 raw_ostream &getStream() { return StringStream; }
86};
87
88} // end anonymous namespace
89
91 char Data[sizeof(Value)];
93 OS.write(Data, sizeof(Data));
94 return 0;
95}
96
98 char Data[sizeof(Value)];
100 OS.write(Data, sizeof(Data));
101 return 0;
102}
103
105 char Data[sizeof(Value)];
106 memcpy(Data, &Value, sizeof(Data));
107 OS.write(Data, sizeof(Data));
108 return 0;
109}
110
111static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
112 encodeULEB128(Str.size(), OS);
113 OS << Str;
114 return 0;
115}
116
117static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
118 writeUint8(OS, Lim.Flags);
119 encodeULEB128(Lim.Minimum, OS);
121 encodeULEB128(Lim.Maximum, OS);
122 return 0;
123}
124
125void WasmWriter::reportError(const Twine &Msg) {
126 ErrHandler(Msg);
127 HasError = true;
128}
129
130void WasmWriter::writeInitExpr(raw_ostream &OS,
131 const WasmYAML::InitExpr &InitExpr) {
132 if (InitExpr.Extended) {
133 InitExpr.Body.writeAsBinary(OS);
134 } else {
135 writeUint8(OS, InitExpr.Inst.Opcode);
136 switch (InitExpr.Inst.Opcode) {
138 encodeSLEB128(InitExpr.Inst.Value.Int32, OS);
139 break;
141 encodeSLEB128(InitExpr.Inst.Value.Int64, OS);
142 break;
144 writeUint32(OS, InitExpr.Inst.Value.Float32);
145 break;
147 writeUint64(OS, InitExpr.Inst.Value.Float64);
148 break;
150 encodeULEB128(InitExpr.Inst.Value.Global, OS);
151 break;
152 default:
153 reportError("unknown opcode in init_expr: " +
154 Twine(InitExpr.Inst.Opcode));
155 return;
156 }
158 }
159}
160
161void WasmWriter::writeSectionContent(raw_ostream &OS,
162 WasmYAML::DylinkSection &Section) {
163 writeStringRef(Section.Name, OS);
164
166 SubSectionWriter SubSection(OS);
167 raw_ostream &SubOS = SubSection.getStream();
168 encodeULEB128(Section.MemorySize, SubOS);
169 encodeULEB128(Section.MemoryAlignment, SubOS);
170 encodeULEB128(Section.TableSize, SubOS);
171 encodeULEB128(Section.TableAlignment, SubOS);
172 SubSection.done();
173
174 if (Section.Needed.size()) {
176 raw_ostream &SubOS = SubSection.getStream();
177 encodeULEB128(Section.Needed.size(), SubOS);
178 for (StringRef Needed : Section.Needed)
179 writeStringRef(Needed, SubOS);
180 SubSection.done();
181 }
182 if (Section.ExportInfo.size()) {
184 raw_ostream &SubOS = SubSection.getStream();
185 encodeULEB128(Section.ExportInfo.size(), SubOS);
186 for (const WasmYAML::DylinkExportInfo &Info : Section.ExportInfo) {
187 writeStringRef(Info.Name, SubOS);
188 encodeULEB128(Info.Flags, SubOS);
189 }
190 SubSection.done();
191 }
192 if (Section.ImportInfo.size()) {
194 raw_ostream &SubOS = SubSection.getStream();
195 encodeULEB128(Section.ImportInfo.size(), SubOS);
196 for (const WasmYAML::DylinkImportInfo &Info : Section.ImportInfo) {
197 writeStringRef(Info.Module, SubOS);
198 writeStringRef(Info.Field, SubOS);
199 encodeULEB128(Info.Flags, SubOS);
200 }
201 SubSection.done();
202 }
203 if (Section.RuntimePath.size()) {
205 raw_ostream &SubOS = SubSection.getStream();
206 encodeULEB128(Section.RuntimePath.size(), SubOS);
207 for (StringRef Path : Section.RuntimePath)
208 writeStringRef(Path, SubOS);
209 SubSection.done();
210 }
211}
212
213void WasmWriter::writeSectionContent(raw_ostream &OS,
214 WasmYAML::LinkingSection &Section) {
215 writeStringRef(Section.Name, OS);
216 encodeULEB128(Section.Version, OS);
217
218 SubSectionWriter SubSection(OS);
219
220 // SYMBOL_TABLE subsection
221 if (Section.SymbolTable.size()) {
223 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
224 for (auto Sym : llvm::enumerate(Section.SymbolTable)) {
225 const WasmYAML::SymbolInfo &Info = Sym.value();
226 assert(Info.Index == Sym.index());
227 writeUint8(SubSection.getStream(), Info.Kind);
228 encodeULEB128(Info.Flags, SubSection.getStream());
229 switch (Info.Kind) {
234 encodeULEB128(Info.ElementIndex, SubSection.getStream());
235 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
237 writeStringRef(Info.Name, SubSection.getStream());
238 break;
240 writeStringRef(Info.Name, SubSection.getStream());
241 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
242 if ((Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
244 encodeULEB128(Info.CommonRef.Size, SubSection.getStream());
245 writeUint8(SubSection.getStream(), Info.CommonRef.Alignment);
246 } else {
247 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
248 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
249 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
250 }
251 }
252 break;
254 encodeULEB128(Info.ElementIndex, SubSection.getStream());
255 break;
256 default:
257 llvm_unreachable("unexpected kind");
258 }
259 }
260
261 SubSection.done();
262 }
263
264 // SEGMENT_NAMES subsection
265 if (Section.SegmentInfos.size()) {
267 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
268 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
269 writeStringRef(SegmentInfo.Name, SubSection.getStream());
270 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
271 encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
272 }
273 SubSection.done();
274 }
275
276 // INIT_FUNCS subsection
277 if (Section.InitFunctions.size()) {
279 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
280 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
281 encodeULEB128(Func.Priority, SubSection.getStream());
282 encodeULEB128(Func.Symbol, SubSection.getStream());
283 }
284 SubSection.done();
285 }
286
287 // COMDAT_INFO subsection
288 if (Section.Comdats.size()) {
290 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
291 for (const auto &C : Section.Comdats) {
292 writeStringRef(C.Name, SubSection.getStream());
293 encodeULEB128(0, SubSection.getStream()); // flags for future use
294 encodeULEB128(C.Entries.size(), SubSection.getStream());
295 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
296 writeUint8(SubSection.getStream(), Entry.Kind);
297 encodeULEB128(Entry.Index, SubSection.getStream());
298 }
299 }
300 SubSection.done();
301 }
302}
303
304void WasmWriter::writeSectionContent(raw_ostream &OS,
305 WasmYAML::NameSection &Section) {
306 writeStringRef(Section.Name, OS);
307 if (Section.FunctionNames.size()) {
309
310 SubSectionWriter SubSection(OS);
311
312 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
313 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
314 encodeULEB128(NameEntry.Index, SubSection.getStream());
315 writeStringRef(NameEntry.Name, SubSection.getStream());
316 }
317
318 SubSection.done();
319 }
320 if (Section.GlobalNames.size()) {
322
323 SubSectionWriter SubSection(OS);
324
325 encodeULEB128(Section.GlobalNames.size(), SubSection.getStream());
326 for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {
327 encodeULEB128(NameEntry.Index, SubSection.getStream());
328 writeStringRef(NameEntry.Name, SubSection.getStream());
329 }
330
331 SubSection.done();
332 }
333 if (Section.DataSegmentNames.size()) {
335
336 SubSectionWriter SubSection(OS);
337
338 encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());
339 for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {
340 encodeULEB128(NameEntry.Index, SubSection.getStream());
341 writeStringRef(NameEntry.Name, SubSection.getStream());
342 }
343
344 SubSection.done();
345 }
346}
347
348void WasmWriter::writeSectionContent(raw_ostream &OS,
349 WasmYAML::ProducersSection &Section) {
350 writeStringRef(Section.Name, OS);
351 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
352 int(!Section.SDKs.empty());
353 if (Fields == 0)
354 return;
355 encodeULEB128(Fields, OS);
356 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
357 std::make_pair(StringRef("processed-by"), &Section.Tools),
358 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
359 if (Field.second->empty())
360 continue;
361 writeStringRef(Field.first, OS);
362 encodeULEB128(Field.second->size(), OS);
363 for (auto &Entry : *Field.second) {
364 writeStringRef(Entry.Name, OS);
365 writeStringRef(Entry.Version, OS);
366 }
367 }
368}
369
370void WasmWriter::writeSectionContent(raw_ostream &OS,
371 WasmYAML::TargetFeaturesSection &Section) {
372 writeStringRef(Section.Name, OS);
373 encodeULEB128(Section.Features.size(), OS);
374 for (auto &E : Section.Features) {
375 writeUint8(OS, E.Prefix);
376 writeStringRef(E.Name, OS);
377 }
378}
379
380void WasmWriter::writeSectionContent(raw_ostream &OS,
381 WasmYAML::CustomSection &Section) {
382 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
383 writeSectionContent(OS, *S);
384 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
385 writeSectionContent(OS, *S);
386 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
387 writeSectionContent(OS, *S);
388 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
389 writeSectionContent(OS, *S);
390 } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
391 writeSectionContent(OS, *S);
392 } else {
393 writeStringRef(Section.Name, OS);
394 Section.Payload.writeAsBinary(OS);
395 }
396}
397
398void WasmWriter::writeSectionContent(raw_ostream &OS,
399 WasmYAML::TypeSection &Section) {
400 encodeULEB128(Section.Signatures.size(), OS);
401 uint32_t ExpectedIndex = 0;
402 for (const WasmYAML::Signature &Sig : Section.Signatures) {
403 if (Sig.Index != ExpectedIndex) {
404 reportError("unexpected type index: " + Twine(Sig.Index));
405 return;
406 }
407 ++ExpectedIndex;
408 writeUint8(OS, Sig.Form);
409 encodeULEB128(Sig.ParamTypes.size(), OS);
410 for (auto ParamType : Sig.ParamTypes)
411 writeUint8(OS, ParamType);
412 encodeULEB128(Sig.ReturnTypes.size(), OS);
413 for (auto ReturnType : Sig.ReturnTypes)
414 writeUint8(OS, ReturnType);
415 }
416}
417
418void WasmWriter::writeSectionContent(raw_ostream &OS,
419 WasmYAML::ImportSection &Section) {
420 encodeULEB128(Section.Imports.size(), OS);
421 for (const WasmYAML::Import &Import : Section.Imports) {
422 writeStringRef(Import.Module, OS);
423 writeStringRef(Import.Field, OS);
424 writeUint8(OS, Import.Kind);
425 switch (Import.Kind) {
427 encodeULEB128(Import.SigIndex, OS);
428 NumImportedFunctions++;
429 break;
431 writeUint8(OS, Import.GlobalImport.Type);
432 writeUint8(OS, Import.GlobalImport.Mutable);
433 NumImportedGlobals++;
434 break;
436 writeUint8(OS, 0); // Reserved 'attribute' field
437 encodeULEB128(Import.SigIndex, OS);
438 NumImportedTags++;
439 break;
441 writeLimits(Import.Memory, OS);
442 break;
444 writeUint8(OS, Import.TableImport.ElemType);
445 writeLimits(Import.TableImport.TableLimits, OS);
446 NumImportedTables++;
447 break;
448 default:
449 reportError("unknown import type: " +Twine(Import.Kind));
450 return;
451 }
452 }
453}
454
455void WasmWriter::writeSectionContent(raw_ostream &OS,
456 WasmYAML::FunctionSection &Section) {
457 encodeULEB128(Section.FunctionTypes.size(), OS);
458 for (uint32_t FuncType : Section.FunctionTypes)
459 encodeULEB128(FuncType, OS);
460}
461
462void WasmWriter::writeSectionContent(raw_ostream &OS,
463 WasmYAML::ExportSection &Section) {
464 encodeULEB128(Section.Exports.size(), OS);
465 for (const WasmYAML::Export &Export : Section.Exports) {
466 writeStringRef(Export.Name, OS);
467 writeUint8(OS, Export.Kind);
468 encodeULEB128(Export.Index, OS);
469 }
470}
471
472void WasmWriter::writeSectionContent(raw_ostream &OS,
473 WasmYAML::StartSection &Section) {
474 encodeULEB128(Section.StartFunction, OS);
475}
476
477void WasmWriter::writeSectionContent(raw_ostream &OS,
478 WasmYAML::TableSection &Section) {
479 encodeULEB128(Section.Tables.size(), OS);
480 uint32_t ExpectedIndex = NumImportedTables;
481 for (auto &Table : Section.Tables) {
482 if (Table.Index != ExpectedIndex) {
483 reportError("unexpected table index: " + Twine(Table.Index));
484 return;
485 }
486 ++ExpectedIndex;
487 writeUint8(OS, Table.ElemType);
488 writeLimits(Table.TableLimits, OS);
489 }
490}
491
492void WasmWriter::writeSectionContent(raw_ostream &OS,
493 WasmYAML::MemorySection &Section) {
494 encodeULEB128(Section.Memories.size(), OS);
495 for (const WasmYAML::Limits &Mem : Section.Memories)
496 writeLimits(Mem, OS);
497}
498
499void WasmWriter::writeSectionContent(raw_ostream &OS,
500 WasmYAML::TagSection &Section) {
501 encodeULEB128(Section.TagTypes.size(), OS);
502 for (uint32_t TagType : Section.TagTypes) {
503 writeUint8(OS, 0); // Reserved 'attribute' field
504 encodeULEB128(TagType, OS);
505 }
506}
507
508void WasmWriter::writeSectionContent(raw_ostream &OS,
509 WasmYAML::GlobalSection &Section) {
510 encodeULEB128(Section.Globals.size(), OS);
511 uint32_t ExpectedIndex = NumImportedGlobals;
512 for (auto &Global : Section.Globals) {
513 if (Global.Index != ExpectedIndex) {
514 reportError("unexpected global index: " + Twine(Global.Index));
515 return;
516 }
517 ++ExpectedIndex;
518 writeUint8(OS, Global.Type);
519 writeUint8(OS, Global.Mutable);
520 writeInitExpr(OS, Global.Init);
521 }
522}
523
524void WasmWriter::writeSectionContent(raw_ostream &OS,
525 WasmYAML::ElemSection &Section) {
526 encodeULEB128(Section.Segments.size(), OS);
527 for (auto &Segment : Section.Segments) {
528 encodeULEB128(Segment.Flags, OS);
530 encodeULEB128(Segment.TableNumber, OS);
531
532 writeInitExpr(OS, Segment.Offset);
533
534 if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC) {
535 // We only support active function table initializers, for which the elem
536 // kind is specified to be written as 0x00 and interpreted to mean
537 // "funcref".
538 if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {
539 reportError("unexpected elemkind: " + Twine(Segment.ElemKind));
540 return;
541 }
542 const uint8_t ElemKind = 0;
543 writeUint8(OS, ElemKind);
544 }
545
546 encodeULEB128(Segment.Functions.size(), OS);
547 for (auto &Function : Segment.Functions)
549 }
550}
551
552void WasmWriter::writeSectionContent(raw_ostream &OS,
553 WasmYAML::CodeSection &Section) {
554 encodeULEB128(Section.Functions.size(), OS);
555 uint32_t ExpectedIndex = NumImportedFunctions;
556 for (auto &Func : Section.Functions) {
557 std::string OutString;
558 raw_string_ostream StringStream(OutString);
559 if (Func.Index != ExpectedIndex) {
560 reportError("unexpected function index: " + Twine(Func.Index));
561 return;
562 }
563 ++ExpectedIndex;
564
565 encodeULEB128(Func.Locals.size(), StringStream);
566 for (auto &LocalDecl : Func.Locals) {
567 encodeULEB128(LocalDecl.Count, StringStream);
568 writeUint8(StringStream, LocalDecl.Type);
569 }
570
571 Func.Body.writeAsBinary(StringStream);
572
573 // Write the section size followed by the content
574 encodeULEB128(OutString.size(), OS);
575 OS << OutString;
576 }
577}
578
579void WasmWriter::writeSectionContent(raw_ostream &OS,
580 WasmYAML::DataSection &Section) {
581 encodeULEB128(Section.Segments.size(), OS);
582 for (auto &Segment : Section.Segments) {
583 encodeULEB128(Segment.InitFlags, OS);
584 if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
585 encodeULEB128(Segment.MemoryIndex, OS);
586 if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)
587 writeInitExpr(OS, Segment.Offset);
588 encodeULEB128(Segment.Content.binary_size(), OS);
589 Segment.Content.writeAsBinary(OS);
590 }
591}
592
593void WasmWriter::writeSectionContent(raw_ostream &OS,
594 WasmYAML::DataCountSection &Section) {
595 encodeULEB128(Section.Count, OS);
596}
597
598void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
599 uint32_t SectionIndex) {
600 switch (Sec.Type) {
602 writeStringRef("reloc.CODE", OS);
603 break;
605 writeStringRef("reloc.DATA", OS);
606 break;
608 auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
609 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
610 break;
611 }
612 default:
613 llvm_unreachable("not yet implemented");
614 }
615
616 encodeULEB128(SectionIndex, OS);
617 encodeULEB128(Sec.Relocations.size(), OS);
618
619 for (auto Reloc : Sec.Relocations) {
620 writeUint8(OS, Reloc.Type);
621 encodeULEB128(Reloc.Offset, OS);
622 encodeULEB128(Reloc.Index, OS);
623 if (wasm::relocTypeHasAddend(Reloc.Type))
624 encodeSLEB128(Reloc.Addend, OS);
625 }
626}
627
628bool WasmWriter::writeWasm(raw_ostream &OS) {
629 // Write headers
631 writeUint32(OS, Obj.Header.Version);
632
633 // Write each section
634 llvm::object::WasmSectionOrderChecker Checker;
635 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
636 StringRef SecName = "";
637 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
638 SecName = S->Name;
639 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
640 reportError("out of order section type: " +
641 wasm::sectionTypeToString(Sec->Type));
642 return false;
643 }
644 encodeULEB128(Sec->Type, OS);
645 std::string OutString;
646 raw_string_ostream StringStream(OutString);
647 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
648 writeSectionContent(StringStream, *S);
649 else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
650 writeSectionContent(StringStream, *S);
651 else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
652 writeSectionContent(StringStream, *S);
653 else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
654 writeSectionContent(StringStream, *S);
655 else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
656 writeSectionContent(StringStream, *S);
657 else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
658 writeSectionContent(StringStream, *S);
659 else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))
660 writeSectionContent(StringStream, *S);
661 else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
662 writeSectionContent(StringStream, *S);
663 else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
664 writeSectionContent(StringStream, *S);
665 else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
666 writeSectionContent(StringStream, *S);
667 else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
668 writeSectionContent(StringStream, *S);
669 else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
670 writeSectionContent(StringStream, *S);
671 else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
672 writeSectionContent(StringStream, *S);
673 else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
674 writeSectionContent(StringStream, *S);
675 else
676 reportError("unknown section type: " + Twine(Sec->Type));
677
678 if (HasError)
679 return false;
680
681 unsigned HeaderSecSizeEncodingLen =
682 Sec->HeaderSecSizeEncodingLen.value_or(5);
683 unsigned RequiredLen = getULEB128Size(OutString.size());
684 // Wasm spec does not allow LEBs larger than 5 bytes
685 assert(RequiredLen <= 5);
686 if (HeaderSecSizeEncodingLen < RequiredLen) {
687 reportError("section header length can't be encoded in a LEB of size " +
688 Twine(HeaderSecSizeEncodingLen));
689 return false;
690 }
691 // Write the section size followed by the content
692 encodeULEB128(OutString.size(), OS, HeaderSecSizeEncodingLen);
693 OS << OutString;
694 }
695
696 // write reloc sections for any section that have relocations
697 uint32_t SectionIndex = 0;
698 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
699 if (Sec->Relocations.empty()) {
700 SectionIndex++;
701 continue;
702 }
703
705 std::string OutString;
706 raw_string_ostream StringStream(OutString);
707 writeRelocSection(StringStream, *Sec, SectionIndex++);
708
709 encodeULEB128(OutString.size(), OS);
710 OS << OutString;
711 }
712
713 return true;
714}
715
716namespace llvm {
717namespace yaml {
718
720 WasmWriter Writer(Doc, EH);
721 return Writer.writeWasm(Out);
722}
723
724} // namespace yaml
725} // namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
static Error reportError(StringRef Message)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
OptimizedStructLayoutField Field
const char * Msg
static int writeUint32(raw_ostream &OS, uint32_t Value)
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)
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & write(unsigned char C)
LLVM_ABI 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:38
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Entry
Definition COFF.h:862
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:393
void write64le(void *P, uint64_t V)
Definition Endian.h:458
void write32le(void *P, uint32_t V)
Definition Endian.h:455
const unsigned WASM_SYMBOL_UNDEFINED
Definition Wasm.h:257
@ WASM_NAMES_DATA_SEGMENT
Definition Wasm.h:199
@ WASM_NAMES_GLOBAL
Definition Wasm.h:198
@ WASM_NAMES_FUNCTION
Definition Wasm.h:196
const char WasmMagic[]
Definition Wasm.h:27
@ WASM_SEC_CODE
Definition Wasm.h:47
@ WASM_SEC_CUSTOM
Definition Wasm.h:37
@ WASM_SEC_DATA
Definition Wasm.h:48
@ WASM_LIMITS_FLAG_HAS_MAX
Definition Wasm.h:168
@ WASM_SYMBOL_TYPE_GLOBAL
Definition Wasm.h:231
@ WASM_SYMBOL_TYPE_DATA
Definition Wasm.h:230
@ WASM_SYMBOL_TYPE_TAG
Definition Wasm.h:233
@ WASM_SYMBOL_TYPE_TABLE
Definition Wasm.h:234
@ WASM_SYMBOL_TYPE_SECTION
Definition Wasm.h:232
@ WASM_SYMBOL_TYPE_FUNCTION
Definition Wasm.h:229
const unsigned WASM_SYMBOL_BINDING_COMMON
Definition Wasm.h:254
const unsigned WASM_SYMBOL_BINDING_MASK
Definition Wasm.h:248
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition Wasm.h:182
@ WASM_DYLINK_RUNTIME_PATH
Definition Wasm.h:216
@ WASM_DYLINK_NEEDED
Definition Wasm.h:213
@ WASM_DYLINK_MEM_INFO
Definition Wasm.h:212
@ WASM_DYLINK_EXPORT_INFO
Definition Wasm.h:214
@ WASM_DYLINK_IMPORT_INFO
Definition Wasm.h:215
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition Wasm.h:175
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition Wasm.h:176
LLVM_ABI bool relocTypeHasAddend(uint32_t type)
Definition Wasm.cpp:66
@ WASM_EXTERNAL_TABLE
Definition Wasm.h:96
@ WASM_EXTERNAL_FUNCTION
Definition Wasm.h:95
@ WASM_EXTERNAL_TAG
Definition Wasm.h:99
@ WASM_EXTERNAL_MEMORY
Definition Wasm.h:97
@ WASM_EXTERNAL_GLOBAL
Definition Wasm.h:98
@ WASM_INIT_FUNCS
Definition Wasm.h:205
@ WASM_COMDAT_INFO
Definition Wasm.h:206
@ WASM_SEGMENT_INFO
Definition Wasm.h:204
@ WASM_SYMBOL_TABLE
Definition Wasm.h:207
@ WASM_OPCODE_F64_CONST
Definition Wasm.h:116
@ WASM_OPCODE_END
Definition Wasm.h:104
@ WASM_OPCODE_F32_CONST
Definition Wasm.h:115
@ WASM_OPCODE_GLOBAL_GET
Definition Wasm.h:109
@ WASM_OPCODE_I64_CONST
Definition Wasm.h:114
@ WASM_OPCODE_I32_CONST
Definition Wasm.h:113
LLVM_ABI llvm::StringRef sectionTypeToString(uint32_t type)
Definition Wasm.cpp:41
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition Wasm.h:259
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
Definition Wasm.h:185
llvm::function_ref< void(const Twine &Msg)> ErrorHandler
Definition yaml2obj.h:68
LLVM_ABI bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
This is an optimization pass for GlobalISel generic memory operations.
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:2554
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Export
Export information to summary.
Definition IPO.h:40
@ Import
Import information from summary.
Definition IPO.h:39
@ Global
Append to llvm.global_dtors.
LLVM_ABI 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:24
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
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:79
wasm::WasmInitExprMVP Inst
Definition WasmYAML.h:70
yaml::BinaryRef Body
Definition WasmYAML.h:71
yaml::Hex32 Minimum
Definition WasmYAML.h:49
yaml::Hex32 Maximum
Definition WasmYAML.h:50
std::vector< std::unique_ptr< Section > > Sections
Definition WasmYAML.h:422
std::vector< Relocation > Relocations
Definition WasmYAML.h:193
std::vector< ValueType > ReturnTypes
Definition WasmYAML.h:158
std::vector< ValueType > ParamTypes
Definition WasmYAML.h:157
union llvm::wasm::WasmInitExprMVP::@234311111124136373374304035273310237314141125040 Value
Common declarations for yaml2obj.