LLVM  14.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 
21 using namespace llvm;
22 
23 namespace {
24 /// This parses a yaml stream that represents a Wasm object file.
25 /// See docs/yaml2obj for the yaml scheema.
26 class WasmWriter {
27 public:
28  WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)
29  : Obj(Obj), ErrHandler(EH) {}
30  bool writeWasm(raw_ostream &OS);
31 
32 private:
33  void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
34  uint32_t SectionIndex);
35 
36  void writeInitExpr(raw_ostream &OS, const wasm::WasmInitExpr &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,
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 
71 class SubSectionWriter {
72  raw_ostream &OS;
73  std::string OutString;
74  raw_string_ostream StringStream;
75 
76 public:
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 
105 static int writeUint8(raw_ostream &OS, uint8_t Value) {
106  char Data[sizeof(Value)];
107  memcpy(Data, &Value, sizeof(Data));
108  OS.write(Data, sizeof(Data));
109  return 0;
110 }
111 
112 static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
113  encodeULEB128(Str.size(), OS);
114  OS << Str;
115  return 0;
116 }
117 
118 static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
119  writeUint8(OS, Lim.Flags);
120  encodeULEB128(Lim.Minimum, OS);
122  encodeULEB128(Lim.Maximum, OS);
123  return 0;
124 }
125 
126 void WasmWriter::reportError(const Twine &Msg) {
127  ErrHandler(Msg);
128  HasError = true;
129 }
130 
131 void WasmWriter::writeInitExpr(raw_ostream &OS,
132  const wasm::WasmInitExpr &InitExpr) {
133  writeUint8(OS, InitExpr.Opcode);
134  switch (InitExpr.Opcode) {
136  encodeSLEB128(InitExpr.Value.Int32, OS);
137  break;
139  encodeSLEB128(InitExpr.Value.Int64, OS);
140  break;
142  writeUint32(OS, InitExpr.Value.Float32);
143  break;
145  writeUint64(OS, InitExpr.Value.Float64);
146  break;
148  encodeULEB128(InitExpr.Value.Global, OS);
149  break;
150  default:
151  reportError("unknown opcode in init_expr: " + Twine(InitExpr.Opcode));
152  return;
153  }
155 }
156 
157 void WasmWriter::writeSectionContent(raw_ostream &OS,
159  writeStringRef(Section.Name, OS);
160 
162  SubSectionWriter SubSection(OS);
163  raw_ostream &SubOS = SubSection.getStream();
164  encodeULEB128(Section.MemorySize, SubOS);
165  encodeULEB128(Section.MemoryAlignment, SubOS);
166  encodeULEB128(Section.TableSize, SubOS);
167  encodeULEB128(Section.TableAlignment, SubOS);
168  SubSection.done();
169 
170  if (Section.Needed.size()) {
172  raw_ostream &SubOS = SubSection.getStream();
173  encodeULEB128(Section.Needed.size(), SubOS);
174  for (StringRef Needed : Section.Needed)
175  writeStringRef(Needed, SubOS);
176  SubSection.done();
177  }
178 }
179 
180 void WasmWriter::writeSectionContent(raw_ostream &OS,
182  writeStringRef(Section.Name, OS);
183  encodeULEB128(Section.Version, OS);
184 
185  SubSectionWriter SubSection(OS);
186 
187  // SYMBOL_TABLE subsection
188  if (Section.SymbolTable.size()) {
190 
191  encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
192 #ifndef NDEBUG
193  uint32_t SymbolIndex = 0;
194 #endif
195  for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
196  assert(Info.Index == SymbolIndex++);
197  writeUint8(SubSection.getStream(), Info.Kind);
198  encodeULEB128(Info.Flags, SubSection.getStream());
199  switch (Info.Kind) {
204  encodeULEB128(Info.ElementIndex, SubSection.getStream());
205  if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
206  (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
207  writeStringRef(Info.Name, SubSection.getStream());
208  break;
210  writeStringRef(Info.Name, SubSection.getStream());
211  if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
212  encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
213  encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
214  encodeULEB128(Info.DataRef.Size, SubSection.getStream());
215  }
216  break;
218  encodeULEB128(Info.ElementIndex, SubSection.getStream());
219  break;
220  default:
221  llvm_unreachable("unexpected kind");
222  }
223  }
224 
225  SubSection.done();
226  }
227 
228  // SEGMENT_NAMES subsection
229  if (Section.SegmentInfos.size()) {
231  encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
232  for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
233  writeStringRef(SegmentInfo.Name, SubSection.getStream());
234  encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
235  encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
236  }
237  SubSection.done();
238  }
239 
240  // INIT_FUNCS subsection
241  if (Section.InitFunctions.size()) {
243  encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
244  for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
245  encodeULEB128(Func.Priority, SubSection.getStream());
246  encodeULEB128(Func.Symbol, SubSection.getStream());
247  }
248  SubSection.done();
249  }
250 
251  // COMDAT_INFO subsection
252  if (Section.Comdats.size()) {
254  encodeULEB128(Section.Comdats.size(), SubSection.getStream());
255  for (const auto &C : Section.Comdats) {
256  writeStringRef(C.Name, SubSection.getStream());
257  encodeULEB128(0, SubSection.getStream()); // flags for future use
258  encodeULEB128(C.Entries.size(), SubSection.getStream());
259  for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
260  writeUint8(SubSection.getStream(), Entry.Kind);
261  encodeULEB128(Entry.Index, SubSection.getStream());
262  }
263  }
264  SubSection.done();
265  }
266 }
267 
268 void WasmWriter::writeSectionContent(raw_ostream &OS,
270  writeStringRef(Section.Name, OS);
271  if (Section.FunctionNames.size()) {
273 
274  SubSectionWriter SubSection(OS);
275 
276  encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
277  for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
278  encodeULEB128(NameEntry.Index, SubSection.getStream());
279  writeStringRef(NameEntry.Name, SubSection.getStream());
280  }
281 
282  SubSection.done();
283  }
284  if (Section.GlobalNames.size()) {
286 
287  SubSectionWriter SubSection(OS);
288 
289  encodeULEB128(Section.GlobalNames.size(), SubSection.getStream());
290  for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {
291  encodeULEB128(NameEntry.Index, SubSection.getStream());
292  writeStringRef(NameEntry.Name, SubSection.getStream());
293  }
294 
295  SubSection.done();
296  }
297  if (Section.DataSegmentNames.size()) {
299 
300  SubSectionWriter SubSection(OS);
301 
302  encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());
303  for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {
304  encodeULEB128(NameEntry.Index, SubSection.getStream());
305  writeStringRef(NameEntry.Name, SubSection.getStream());
306  }
307 
308  SubSection.done();
309  }
310 }
311 
312 void WasmWriter::writeSectionContent(raw_ostream &OS,
314  writeStringRef(Section.Name, OS);
315  int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
316  int(!Section.SDKs.empty());
317  if (Fields == 0)
318  return;
319  encodeULEB128(Fields, OS);
320  for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
321  std::make_pair(StringRef("processed-by"), &Section.Tools),
322  std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
323  if (Field.second->empty())
324  continue;
325  writeStringRef(Field.first, OS);
326  encodeULEB128(Field.second->size(), OS);
327  for (auto &Entry : *Field.second) {
328  writeStringRef(Entry.Name, OS);
329  writeStringRef(Entry.Version, OS);
330  }
331  }
332 }
333 
334 void WasmWriter::writeSectionContent(raw_ostream &OS,
336  writeStringRef(Section.Name, OS);
337  encodeULEB128(Section.Features.size(), OS);
338  for (auto &E : Section.Features) {
339  writeUint8(OS, E.Prefix);
340  writeStringRef(E.Name, OS);
341  }
342 }
343 
344 void WasmWriter::writeSectionContent(raw_ostream &OS,
346  if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
347  writeSectionContent(OS, *S);
348  } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
349  writeSectionContent(OS, *S);
350  } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
351  writeSectionContent(OS, *S);
352  } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
353  writeSectionContent(OS, *S);
354  } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
355  writeSectionContent(OS, *S);
356  } else {
357  writeStringRef(Section.Name, OS);
358  Section.Payload.writeAsBinary(OS);
359  }
360 }
361 
362 void WasmWriter::writeSectionContent(raw_ostream &OS,
364  encodeULEB128(Section.Signatures.size(), OS);
365  uint32_t ExpectedIndex = 0;
366  for (const WasmYAML::Signature &Sig : Section.Signatures) {
367  if (Sig.Index != ExpectedIndex) {
368  reportError("unexpected type index: " + Twine(Sig.Index));
369  return;
370  }
371  ++ExpectedIndex;
372  writeUint8(OS, Sig.Form);
373  encodeULEB128(Sig.ParamTypes.size(), OS);
374  for (auto ParamType : Sig.ParamTypes)
375  writeUint8(OS, ParamType);
376  encodeULEB128(Sig.ReturnTypes.size(), OS);
377  for (auto ReturnType : Sig.ReturnTypes)
378  writeUint8(OS, ReturnType);
379  }
380 }
381 
382 void WasmWriter::writeSectionContent(raw_ostream &OS,
384  encodeULEB128(Section.Imports.size(), OS);
385  for (const WasmYAML::Import &Import : Section.Imports) {
386  writeStringRef(Import.Module, OS);
387  writeStringRef(Import.Field, OS);
388  writeUint8(OS, Import.Kind);
389  switch (Import.Kind) {
391  encodeULEB128(Import.SigIndex, OS);
392  NumImportedFunctions++;
393  break;
395  writeUint8(OS, Import.GlobalImport.Type);
396  writeUint8(OS, Import.GlobalImport.Mutable);
397  NumImportedGlobals++;
398  break;
400  writeUint8(OS, 0); // Reserved 'attribute' field
401  encodeULEB128(Import.SigIndex, OS);
402  NumImportedTags++;
403  break;
405  writeLimits(Import.Memory, OS);
406  break;
408  writeUint8(OS, Import.TableImport.ElemType);
409  writeLimits(Import.TableImport.TableLimits, OS);
410  NumImportedTables++;
411  break;
412  default:
413  reportError("unknown import type: " +Twine(Import.Kind));
414  return;
415  }
416  }
417 }
418 
419 void WasmWriter::writeSectionContent(raw_ostream &OS,
421  encodeULEB128(Section.FunctionTypes.size(), OS);
422  for (uint32_t FuncType : Section.FunctionTypes)
423  encodeULEB128(FuncType, OS);
424 }
425 
426 void WasmWriter::writeSectionContent(raw_ostream &OS,
428  encodeULEB128(Section.Exports.size(), OS);
429  for (const WasmYAML::Export &Export : Section.Exports) {
430  writeStringRef(Export.Name, OS);
431  writeUint8(OS, Export.Kind);
432  encodeULEB128(Export.Index, OS);
433  }
434 }
435 
436 void WasmWriter::writeSectionContent(raw_ostream &OS,
438  encodeULEB128(Section.StartFunction, OS);
439 }
440 
441 void WasmWriter::writeSectionContent(raw_ostream &OS,
443  encodeULEB128(Section.Tables.size(), OS);
444  uint32_t ExpectedIndex = NumImportedTables;
445  for (auto &Table : Section.Tables) {
446  if (Table.Index != ExpectedIndex) {
447  reportError("unexpected table index: " + Twine(Table.Index));
448  return;
449  }
450  ++ExpectedIndex;
451  writeUint8(OS, Table.ElemType);
452  writeLimits(Table.TableLimits, OS);
453  }
454 }
455 
456 void WasmWriter::writeSectionContent(raw_ostream &OS,
458  encodeULEB128(Section.Memories.size(), OS);
459  for (const WasmYAML::Limits &Mem : Section.Memories)
460  writeLimits(Mem, OS);
461 }
462 
463 void WasmWriter::writeSectionContent(raw_ostream &OS,
465  encodeULEB128(Section.TagTypes.size(), OS);
466  for (uint32_t TagType : Section.TagTypes) {
467  writeUint8(OS, 0); // Reserved 'attribute' field
468  encodeULEB128(TagType, OS);
469  }
470 }
471 
472 void WasmWriter::writeSectionContent(raw_ostream &OS,
474  encodeULEB128(Section.Globals.size(), OS);
475  uint32_t ExpectedIndex = NumImportedGlobals;
476  for (auto &Global : Section.Globals) {
477  if (Global.Index != ExpectedIndex) {
478  reportError("unexpected global index: " + Twine(Global.Index));
479  return;
480  }
481  ++ExpectedIndex;
482  writeUint8(OS, Global.Type);
483  writeUint8(OS, Global.Mutable);
484  writeInitExpr(OS, Global.InitExpr);
485  }
486 }
487 
488 void WasmWriter::writeSectionContent(raw_ostream &OS,
490  encodeULEB128(Section.Segments.size(), OS);
491  for (auto &Segment : Section.Segments) {
492  encodeULEB128(Segment.Flags, OS);
493  if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
494  encodeULEB128(Segment.TableNumber, OS);
495 
496  writeInitExpr(OS, Segment.Offset);
497 
498  if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
499  // We only support active function table initializers, for which the elem
500  // kind is specified to be written as 0x00 and interpreted to mean
501  // "funcref".
502  if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {
503  reportError("unexpected elemkind: " + Twine(Segment.ElemKind));
504  return;
505  }
506  const uint8_t ElemKind = 0;
507  writeUint8(OS, ElemKind);
508  }
509 
510  encodeULEB128(Segment.Functions.size(), OS);
511  for (auto &Function : Segment.Functions)
512  encodeULEB128(Function, OS);
513  }
514 }
515 
516 void WasmWriter::writeSectionContent(raw_ostream &OS,
518  encodeULEB128(Section.Functions.size(), OS);
519  uint32_t ExpectedIndex = NumImportedFunctions;
520  for (auto &Func : Section.Functions) {
521  std::string OutString;
522  raw_string_ostream StringStream(OutString);
523  if (Func.Index != ExpectedIndex) {
524  reportError("unexpected function index: " + Twine(Func.Index));
525  return;
526  }
527  ++ExpectedIndex;
528 
529  encodeULEB128(Func.Locals.size(), StringStream);
530  for (auto &LocalDecl : Func.Locals) {
531  encodeULEB128(LocalDecl.Count, StringStream);
532  writeUint8(StringStream, LocalDecl.Type);
533  }
534 
535  Func.Body.writeAsBinary(StringStream);
536 
537  // Write the section size followed by the content
538  StringStream.flush();
539  encodeULEB128(OutString.size(), OS);
540  OS << OutString;
541  }
542 }
543 
544 void WasmWriter::writeSectionContent(raw_ostream &OS,
546  encodeULEB128(Section.Segments.size(), OS);
547  for (auto &Segment : Section.Segments) {
548  encodeULEB128(Segment.InitFlags, OS);
549  if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
550  encodeULEB128(Segment.MemoryIndex, OS);
551  if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)
552  writeInitExpr(OS, Segment.Offset);
553  encodeULEB128(Segment.Content.binary_size(), OS);
554  Segment.Content.writeAsBinary(OS);
555  }
556 }
557 
558 void WasmWriter::writeSectionContent(raw_ostream &OS,
560  encodeULEB128(Section.Count, OS);
561 }
562 
563 void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
564  uint32_t SectionIndex) {
565  switch (Sec.Type) {
566  case wasm::WASM_SEC_CODE:
567  writeStringRef("reloc.CODE", OS);
568  break;
569  case wasm::WASM_SEC_DATA:
570  writeStringRef("reloc.DATA", OS);
571  break;
572  case wasm::WASM_SEC_CUSTOM: {
573  auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
574  writeStringRef(("reloc." + CustomSection->Name).str(), OS);
575  break;
576  }
577  default:
578  llvm_unreachable("not yet implemented");
579  }
580 
581  encodeULEB128(SectionIndex, OS);
582  encodeULEB128(Sec.Relocations.size(), OS);
583 
584  for (auto Reloc : Sec.Relocations) {
585  writeUint8(OS, Reloc.Type);
586  encodeULEB128(Reloc.Offset, OS);
587  encodeULEB128(Reloc.Index, OS);
588  switch (Reloc.Type) {
589  case wasm::R_WASM_MEMORY_ADDR_LEB:
590  case wasm::R_WASM_MEMORY_ADDR_LEB64:
591  case wasm::R_WASM_MEMORY_ADDR_SLEB:
592  case wasm::R_WASM_MEMORY_ADDR_SLEB64:
593  case wasm::R_WASM_MEMORY_ADDR_I32:
594  case wasm::R_WASM_MEMORY_ADDR_I64:
595  case wasm::R_WASM_FUNCTION_OFFSET_I32:
596  case wasm::R_WASM_FUNCTION_OFFSET_I64:
597  case wasm::R_WASM_SECTION_OFFSET_I32:
598  encodeSLEB128(Reloc.Addend, OS);
599  break;
600  }
601  }
602 }
603 
604 bool WasmWriter::writeWasm(raw_ostream &OS) {
605  // Write headers
607  writeUint32(OS, Obj.Header.Version);
608 
609  // Write each section
611  for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
612  StringRef SecName = "";
613  if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
614  SecName = S->Name;
615  if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
616  reportError("out of order section type: " + Twine(Sec->Type));
617  return false;
618  }
619  encodeULEB128(Sec->Type, OS);
620  std::string OutString;
621  raw_string_ostream StringStream(OutString);
622  if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
623  writeSectionContent(StringStream, *S);
624  else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
625  writeSectionContent(StringStream, *S);
626  else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
627  writeSectionContent(StringStream, *S);
628  else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
629  writeSectionContent(StringStream, *S);
630  else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
631  writeSectionContent(StringStream, *S);
632  else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
633  writeSectionContent(StringStream, *S);
634  else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))
635  writeSectionContent(StringStream, *S);
636  else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
637  writeSectionContent(StringStream, *S);
638  else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
639  writeSectionContent(StringStream, *S);
640  else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
641  writeSectionContent(StringStream, *S);
642  else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
643  writeSectionContent(StringStream, *S);
644  else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
645  writeSectionContent(StringStream, *S);
646  else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
647  writeSectionContent(StringStream, *S);
648  else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
649  writeSectionContent(StringStream, *S);
650  else
651  reportError("unknown section type: " + Twine(Sec->Type));
652 
653  if (HasError)
654  return false;
655 
656  StringStream.flush();
657 
658  // Write the section size followed by the content
659  encodeULEB128(OutString.size(), OS);
660  OS << OutString;
661  }
662 
663  // write reloc sections for any section that have relocations
664  uint32_t SectionIndex = 0;
665  for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
666  if (Sec->Relocations.empty()) {
667  SectionIndex++;
668  continue;
669  }
670 
672  std::string OutString;
673  raw_string_ostream StringStream(OutString);
674  writeRelocSection(StringStream, *Sec, SectionIndex++);
675  StringStream.flush();
676 
677  encodeULEB128(OutString.size(), OS);
678  OS << OutString;
679  }
680 
681  return true;
682 }
683 
684 namespace llvm {
685 namespace yaml {
686 
688  WasmWriter Writer(Doc, EH);
689  return Writer.writeWasm(Out);
690 }
691 
692 } // namespace yaml
693 } // namespace llvm
llvm::object::WasmSectionOrderChecker
Definition: Wasm.h:304
llvm::wasm::WASM_EXTERNAL_FUNCTION
@ WASM_EXTERNAL_FUNCTION
Definition: Wasm.h:266
llvm::wasm::WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_SECTION
Definition: Wasm.h:373
llvm::WasmYAML::GlobalSection
Definition: WasmYAML.h:336
llvm::WasmYAML::Section::Relocations
std::vector< Relocation > Relocations
Definition: WasmYAML.h:181
llvm::WasmYAML::InitFunction
Definition: WasmYAML.h:161
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
ObjectYAML.h
writeLimits
static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS)
Definition: WasmEmitter.cpp:118
llvm::WasmYAML::ProducersSection
Definition: WasmYAML.h:252
llvm::wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
Definition: Wasm.h:327
llvm::WasmYAML::NameEntry::Index
uint32_t Index
Definition: WasmYAML.h:122
llvm::Function
Definition: Function.h:62
llvm::wasm::WASM_OPCODE_I32_CONST
@ WASM_OPCODE_I32_CONST
Definition: Wasm.h:283
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
llvm::object::WasmSectionOrderChecker::isValidSectionOrder
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
Definition: WasmObjectFile.cpp:1960
llvm::support::endian::write32le
void write32le(void *P, uint32_t V)
Definition: Endian.h:416
writeUint32
static int writeUint32(raw_ostream &OS, uint32_t Value)
Definition: WasmEmitter.cpp:98
llvm::wasm::WASM_OPCODE_F32_CONST
@ WASM_OPCODE_F32_CONST
Definition: Wasm.h:285
llvm::wasm::WASM_SYMBOL_TYPE_TABLE
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:375
llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:372
llvm::WasmYAML::DataSection
Definition: WasmYAML.h:386
llvm::wasm::WASM_INIT_FUNCS
@ WASM_INIT_FUNCS
Definition: Wasm.h:347
llvm::WasmYAML::TableSection
Definition: WasmYAML.h:306
llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition: Wasm.h:318
writeUint8
static int writeUint8(raw_ostream &OS, uint8_t Value)
Definition: WasmEmitter.cpp:105
llvm::WasmYAML::ElemSection
Definition: WasmYAML.h:366
llvm::WasmYAML::SegmentInfo::Name
StringRef Name
Definition: WasmYAML.h:138
llvm::wasm::WASM_SYMBOL_UNDEFINED
const unsigned WASM_SYMBOL_UNDEFINED
Definition: Wasm.h:396
llvm::wasm::WASM_NAMES_FUNCTION
@ WASM_NAMES_FUNCTION
Definition: Wasm.h:338
llvm::WasmYAML::MemorySection
Definition: WasmYAML.h:316
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::wasm::WASM_EXTERNAL_GLOBAL
@ WASM_EXTERNAL_GLOBAL
Definition: Wasm.h:269
llvm::wasm::WASM_OPCODE_END
@ WASM_OPCODE_END
Definition: Wasm.h:275
llvm::wasm::WASM_LIMITS_FLAG_HAS_MAX
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:312
llvm::WasmYAML::Import
Definition: WasmYAML.h:80
llvm::WasmYAML::CustomSection
Definition: WasmYAML.h:184
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:78
llvm::wasm::WasmInitExpr::Global
uint32_t Global
Definition: Wasm.h:101
llvm::WasmYAML::NameSection
Definition: WasmYAML.h:224
llvm::WasmYAML::Section
Definition: WasmYAML.h:176
llvm::encodeSLEB128
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
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::WasmYAML::FunctionSection
Definition: WasmYAML.h:296
llvm::wasm::WasmInitExpr::Float64
uint64_t Float64
Definition: Wasm.h:100
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
int
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
Definition: README.txt:536
reportError
static Error reportError(StringRef Message)
Definition: BitcodeAnalyzer.cpp:19
llvm::WasmYAML::Limits::Maximum
yaml::Hex32 Maximum
Definition: WasmYAML.h:50
llvm::wasm::WasmInitExpr::Int64
int64_t Int64
Definition: Wasm.h:98
llvm::WasmYAML::ComdatEntry
Definition: WasmYAML.h:166
llvm::WasmYAML::Signature::ReturnTypes
std::vector< ValueType > ReturnTypes
Definition: WasmYAML.h:147
llvm::WasmYAML::CodeSection
Definition: WasmYAML.h:376
llvm::WasmYAML::NameEntry
Definition: WasmYAML.h:121
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:220
llvm::wasm::WasmInitExpr::Value
union llvm::wasm::WasmInitExpr::@165 Value
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::WasmYAML::SegmentInfo::Flags
SegmentFlags Flags
Definition: WasmYAML.h:140
llvm::raw_ostream::flush
void flush()
Definition: raw_ostream.h:186
llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:370
llvm::WasmYAML::SymbolInfo
Definition: WasmYAML.h:150
writeStringRef
static int writeStringRef(const StringRef &Str, raw_ostream &OS)
Definition: WasmEmitter.cpp:112
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::WasmYAML::Limits
Definition: WasmYAML.h:47
Wasm.h
llvm::PassSummaryAction::Import
@ Import
Import information from summary.
llvm::WasmYAML::ExportSection
Definition: WasmYAML.h:346
llvm::wasm::WasmInitExpr::Float32
uint32_t Float32
Definition: Wasm.h:99
llvm::WasmYAML::Signature::Index
uint32_t Index
Definition: WasmYAML.h:144
llvm::wasm::WASM_EXTERNAL_TABLE
@ WASM_EXTERNAL_TABLE
Definition: Wasm.h:267
llvm::WasmYAML::Section::Type
SectionType Type
Definition: WasmYAML.h:180
llvm::WasmYAML::SegmentInfo
Definition: WasmYAML.h:136
llvm::wasm::WASM_OPCODE_GLOBAL_GET
@ WASM_OPCODE_GLOBAL_GET
Definition: Wasm.h:279
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:168
llvm::wasm::WASM_EXTERNAL_TAG
@ WASM_EXTERNAL_TAG
Definition: Wasm.h:270
uint64_t
llvm::WasmYAML::Signature::Form
SignatureForm Form
Definition: WasmYAML.h:145
llvm::wasm::WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition: Wasm.h:398
LEB128.h
llvm::WasmYAML::StartSection
Definition: WasmYAML.h:356
llvm::wasm::ValType::FUNCREF
@ FUNCREF
llvm::wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition: Wasm.h:319
llvm::WasmYAML::TargetFeaturesSection
Definition: WasmYAML.h:265
llvm::wasm::WASM_SYMBOL_TYPE_TAG
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:374
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::wasm::WASM_NAMES_DATA_SEGMENT
@ WASM_NAMES_DATA_SEGMENT
Definition: Wasm.h:341
llvm::ARM::WinEH::ReturnType
ReturnType
Definition: ARMWinEH.h:25
llvm::wasm::WASM_SEC_CUSTOM
@ WASM_SEC_CUSTOM
Definition: Wasm.h:235
llvm::wasm::WasmInitExpr::Int32
int32_t Int32
Definition: Wasm.h:97
yaml2obj.h
llvm::WasmYAML::Signature
Definition: WasmYAML.h:143
llvm::wasm::WASM_SEGMENT_INFO
@ WASM_SEGMENT_INFO
Definition: Wasm.h:346
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
uint32_t
llvm::yaml::yaml2wasm
bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
Definition: WasmEmitter.cpp:687
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
writeUint64
static int writeUint64(raw_ostream &OS, uint64_t Value)
Definition: WasmEmitter.cpp:91
llvm::ifs::IFSSymbolType::Func
@ Func
llvm::wasm::WASM_NAMES_GLOBAL
@ WASM_NAMES_GLOBAL
Definition: Wasm.h:340
llvm::WasmYAML::Object
Definition: WasmYAML.h:406
llvm::WasmYAML::DataCountSection
Definition: WasmYAML.h:396
llvm::wasm::WASM_DYLINK_NEEDED
@ WASM_DYLINK_NEEDED
Definition: Wasm.h:355
llvm::WasmYAML::TagSection
Definition: WasmYAML.h:326
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::wasm::WasmMagic
const char WasmMagic[]
Definition: Wasm.h:26
llvm::WasmYAML::Limits::Flags
LimitFlags Flags
Definition: WasmYAML.h:48
llvm::WasmYAML::SegmentInfo::Alignment
uint32_t Alignment
Definition: WasmYAML.h:139
llvm::WasmYAML::LinkingSection
Definition: WasmYAML.h:237
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::wasm::WasmInitExpr
Definition: Wasm.h:94
llvm::wasm::WASM_DYLINK_MEM_INFO
@ WASM_DYLINK_MEM_INFO
Definition: Wasm.h:354
llvm::wasm::WASM_SYMBOL_TABLE
@ WASM_SYMBOL_TABLE
Definition: Wasm.h:349
llvm::WasmYAML::NameEntry::Name
StringRef Name
Definition: WasmYAML.h:123
llvm::support::endian::write64le
void write64le(void *P, uint64_t V)
Definition: Endian.h:417
llvm::WasmYAML::Limits::Minimum
yaml::Hex32 Minimum
Definition: WasmYAML.h:49
llvm::WasmYAML::Export
Definition: WasmYAML.h:59
llvm::WasmYAML::TypeSection
Definition: WasmYAML.h:276
llvm::WasmYAML::Signature::ParamTypes
std::vector< ValueType > ParamTypes
Definition: WasmYAML.h:146
llvm::pdb::PDB_DataKind::Global
@ Global
llvm::wasm::WASM_EXTERNAL_MEMORY
@ WASM_EXTERNAL_MEMORY
Definition: Wasm.h:268
llvm::encodeULEB128
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
llvm::wasm::WASM_COMDAT_INFO
@ WASM_COMDAT_INFO
Definition: Wasm.h:348
llvm::wasm::WASM_OPCODE_F64_CONST
@ WASM_OPCODE_F64_CONST
Definition: Wasm.h:286
llvm::wasm::WasmInitExpr::Opcode
uint8_t Opcode
Definition: Wasm.h:95
llvm::wasm::WASM_SEC_CODE
@ WASM_SEC_CODE
Definition: Wasm.h:245
llvm::OptimizedStructLayoutField
A field in a structure.
Definition: OptimizedStructLayout.h:45
llvm::wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition: Wasm.h:324
llvm::wasm::WASM_SEC_DATA
@ WASM_SEC_DATA
Definition: Wasm.h:246
Endian.h
llvm::WasmYAML::ImportSection
Definition: WasmYAML.h:286
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::pdb::PDB_SymType::Export
@ Export
llvm::wasm::WASM_SYMBOL_TYPE_DATA
@ WASM_SYMBOL_TYPE_DATA
Definition: Wasm.h:371
llvm::wasm::WASM_OPCODE_I64_CONST
@ WASM_OPCODE_I64_CONST
Definition: Wasm.h:284