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  writeUint32(OS, Import.TagImport.Attribute);
401  writeUint32(OS, Import.TagImport.SigIndex);
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.Tags.size(), OS);
466  uint32_t ExpectedIndex = NumImportedTags;
467  for (auto &Tag : Section.Tags) {
468  if (Tag.Index != ExpectedIndex) {
469  reportError("unexpected tag index: " + Twine(Tag.Index));
470  return;
471  }
472  ++ExpectedIndex;
473  encodeULEB128(Tag.Attribute, OS);
474  encodeULEB128(Tag.SigIndex, OS);
475  }
476 }
477 
478 void WasmWriter::writeSectionContent(raw_ostream &OS,
480  encodeULEB128(Section.Globals.size(), OS);
481  uint32_t ExpectedIndex = NumImportedGlobals;
482  for (auto &Global : Section.Globals) {
483  if (Global.Index != ExpectedIndex) {
484  reportError("unexpected global index: " + Twine(Global.Index));
485  return;
486  }
487  ++ExpectedIndex;
488  writeUint8(OS, Global.Type);
489  writeUint8(OS, Global.Mutable);
490  writeInitExpr(OS, Global.InitExpr);
491  }
492 }
493 
494 void WasmWriter::writeSectionContent(raw_ostream &OS,
496  encodeULEB128(Section.Segments.size(), OS);
497  for (auto &Segment : Section.Segments) {
498  encodeULEB128(Segment.Flags, OS);
499  if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
500  encodeULEB128(Segment.TableNumber, OS);
501 
502  writeInitExpr(OS, Segment.Offset);
503 
504  if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
505  // We only support active function table initializers, for which the elem
506  // kind is specified to be written as 0x00 and interpreted to mean
507  // "funcref".
508  if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {
509  reportError("unexpected elemkind: " + Twine(Segment.ElemKind));
510  return;
511  }
512  const uint8_t ElemKind = 0;
513  writeUint8(OS, ElemKind);
514  }
515 
516  encodeULEB128(Segment.Functions.size(), OS);
517  for (auto &Function : Segment.Functions)
518  encodeULEB128(Function, OS);
519  }
520 }
521 
522 void WasmWriter::writeSectionContent(raw_ostream &OS,
524  encodeULEB128(Section.Functions.size(), OS);
525  uint32_t ExpectedIndex = NumImportedFunctions;
526  for (auto &Func : Section.Functions) {
527  std::string OutString;
528  raw_string_ostream StringStream(OutString);
529  if (Func.Index != ExpectedIndex) {
530  reportError("unexpected function index: " + Twine(Func.Index));
531  return;
532  }
533  ++ExpectedIndex;
534 
535  encodeULEB128(Func.Locals.size(), StringStream);
536  for (auto &LocalDecl : Func.Locals) {
537  encodeULEB128(LocalDecl.Count, StringStream);
538  writeUint8(StringStream, LocalDecl.Type);
539  }
540 
541  Func.Body.writeAsBinary(StringStream);
542 
543  // Write the section size followed by the content
544  StringStream.flush();
545  encodeULEB128(OutString.size(), OS);
546  OS << OutString;
547  }
548 }
549 
550 void WasmWriter::writeSectionContent(raw_ostream &OS,
552  encodeULEB128(Section.Segments.size(), OS);
553  for (auto &Segment : Section.Segments) {
554  encodeULEB128(Segment.InitFlags, OS);
555  if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
556  encodeULEB128(Segment.MemoryIndex, OS);
557  if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)
558  writeInitExpr(OS, Segment.Offset);
559  encodeULEB128(Segment.Content.binary_size(), OS);
560  Segment.Content.writeAsBinary(OS);
561  }
562 }
563 
564 void WasmWriter::writeSectionContent(raw_ostream &OS,
566  encodeULEB128(Section.Count, OS);
567 }
568 
569 void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
570  uint32_t SectionIndex) {
571  switch (Sec.Type) {
572  case wasm::WASM_SEC_CODE:
573  writeStringRef("reloc.CODE", OS);
574  break;
575  case wasm::WASM_SEC_DATA:
576  writeStringRef("reloc.DATA", OS);
577  break;
578  case wasm::WASM_SEC_CUSTOM: {
579  auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
580  writeStringRef(("reloc." + CustomSection->Name).str(), OS);
581  break;
582  }
583  default:
584  llvm_unreachable("not yet implemented");
585  }
586 
587  encodeULEB128(SectionIndex, OS);
588  encodeULEB128(Sec.Relocations.size(), OS);
589 
590  for (auto Reloc : Sec.Relocations) {
591  writeUint8(OS, Reloc.Type);
592  encodeULEB128(Reloc.Offset, OS);
593  encodeULEB128(Reloc.Index, OS);
594  switch (Reloc.Type) {
595  case wasm::R_WASM_MEMORY_ADDR_LEB:
596  case wasm::R_WASM_MEMORY_ADDR_LEB64:
597  case wasm::R_WASM_MEMORY_ADDR_SLEB:
598  case wasm::R_WASM_MEMORY_ADDR_SLEB64:
599  case wasm::R_WASM_MEMORY_ADDR_I32:
600  case wasm::R_WASM_MEMORY_ADDR_I64:
601  case wasm::R_WASM_FUNCTION_OFFSET_I32:
602  case wasm::R_WASM_FUNCTION_OFFSET_I64:
603  case wasm::R_WASM_SECTION_OFFSET_I32:
604  encodeSLEB128(Reloc.Addend, OS);
605  break;
606  }
607  }
608 }
609 
610 bool WasmWriter::writeWasm(raw_ostream &OS) {
611  // Write headers
613  writeUint32(OS, Obj.Header.Version);
614 
615  // Write each section
617  for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
618  StringRef SecName = "";
619  if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
620  SecName = S->Name;
621  if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
622  reportError("out of order section type: " + Twine(Sec->Type));
623  return false;
624  }
625  encodeULEB128(Sec->Type, OS);
626  std::string OutString;
627  raw_string_ostream StringStream(OutString);
628  if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
629  writeSectionContent(StringStream, *S);
630  else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
631  writeSectionContent(StringStream, *S);
632  else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
633  writeSectionContent(StringStream, *S);
634  else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
635  writeSectionContent(StringStream, *S);
636  else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
637  writeSectionContent(StringStream, *S);
638  else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
639  writeSectionContent(StringStream, *S);
640  else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))
641  writeSectionContent(StringStream, *S);
642  else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
643  writeSectionContent(StringStream, *S);
644  else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
645  writeSectionContent(StringStream, *S);
646  else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
647  writeSectionContent(StringStream, *S);
648  else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
649  writeSectionContent(StringStream, *S);
650  else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
651  writeSectionContent(StringStream, *S);
652  else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
653  writeSectionContent(StringStream, *S);
654  else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
655  writeSectionContent(StringStream, *S);
656  else
657  reportError("unknown section type: " + Twine(Sec->Type));
658 
659  if (HasError)
660  return false;
661 
662  StringStream.flush();
663 
664  // Write the section size followed by the content
665  encodeULEB128(OutString.size(), OS);
666  OS << OutString;
667  }
668 
669  // write reloc sections for any section that have relocations
670  uint32_t SectionIndex = 0;
671  for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
672  if (Sec->Relocations.empty()) {
673  SectionIndex++;
674  continue;
675  }
676 
678  std::string OutString;
679  raw_string_ostream StringStream(OutString);
680  writeRelocSection(StringStream, *Sec, SectionIndex++);
681  StringStream.flush();
682 
683  encodeULEB128(OutString.size(), OS);
684  OS << OutString;
685  }
686 
687  return true;
688 }
689 
690 namespace llvm {
691 namespace yaml {
692 
694  WasmWriter Writer(Doc, EH);
695  return Writer.writeWasm(Out);
696 }
697 
698 } // namespace yaml
699 } // namespace llvm
llvm::object::WasmSectionOrderChecker
Definition: Wasm.h:308
llvm::wasm::WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_SECTION
Definition: Wasm.h:370
llvm::WasmYAML::GlobalSection
Definition: WasmYAML.h:335
llvm::WasmYAML::Section::Relocations
std::vector< Relocation > Relocations
Definition: WasmYAML.h:187
llvm::WasmYAML::InitFunction
Definition: WasmYAML.h:167
llvm
---------------------— PointerInfo ------------------------------------—
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:251
llvm::wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
Definition: Wasm.h:325
llvm::WasmYAML::NameEntry::Index
uint32_t Index
Definition: WasmYAML.h:128
llvm::wasm::WASM_EXTERNAL_TABLE
@ WASM_EXTERNAL_TABLE
Definition: Wasm.h:266
llvm::Function
Definition: Function.h:61
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:625
llvm::wasm::WASM_SEGMENT_INFO
@ WASM_SEGMENT_INFO
Definition: Wasm.h:344
llvm::object::WasmSectionOrderChecker::isValidSectionOrder
bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
Definition: WasmObjectFile.cpp:1939
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_SYMBOL_TYPE_TABLE
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:372
llvm::wasm::WASM_SEC_CODE
@ WASM_SEC_CODE
Definition: Wasm.h:244
llvm::wasm::WASM_EXTERNAL_MEMORY
@ WASM_EXTERNAL_MEMORY
Definition: Wasm.h:267
llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:369
llvm::wasm::WASM_OPCODE_END
@ WASM_OPCODE_END
Definition: Wasm.h:274
llvm::WasmYAML::DataSection
Definition: WasmYAML.h:385
llvm::wasm::WASM_COMDAT_INFO
@ WASM_COMDAT_INFO
Definition: Wasm.h:346
llvm::WasmYAML::TableSection
Definition: WasmYAML.h:305
writeUint8
static int writeUint8(raw_ostream &OS, uint8_t Value)
Definition: WasmEmitter.cpp:105
llvm::WasmYAML::ElemSection
Definition: WasmYAML.h:365
llvm::WasmYAML::SegmentInfo::Name
StringRef Name
Definition: WasmYAML.h:144
llvm::wasm::WASM_OPCODE_GLOBAL_GET
@ WASM_OPCODE_GLOBAL_GET
Definition: Wasm.h:278
llvm::wasm::WASM_SYMBOL_UNDEFINED
const unsigned WASM_SYMBOL_UNDEFINED
Definition: Wasm.h:393
llvm::WasmYAML::MemorySection
Definition: WasmYAML.h:315
llvm::dwarf::Tag
Tag
Definition: Dwarf.h:104
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::WasmYAML::Import
Definition: WasmYAML.h:86
llvm::WasmYAML::CustomSection
Definition: WasmYAML.h:190
llvm::ARMBuildAttrs::Section
@ Section
Legacy Tags.
Definition: ARMBuildAttributes.h:78
llvm::wasm::WasmInitExpr::Global
uint32_t Global
Definition: Wasm.h:94
llvm::WasmYAML::NameSection
Definition: WasmYAML.h:223
llvm::WasmYAML::Section
Definition: WasmYAML.h:182
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:295
llvm::wasm::WasmInitExpr::Float64
uint64_t Float64
Definition: Wasm.h:93
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
llvm::wasm::WasmInitExpr::Value
union llvm::wasm::WasmInitExpr::@163 Value
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:91
llvm::WasmYAML::ComdatEntry
Definition: WasmYAML.h:172
llvm::wasm::WASM_NAMES_FUNCTION
@ WASM_NAMES_FUNCTION
Definition: Wasm.h:336
llvm::WasmYAML::Signature::ReturnTypes
std::vector< ValueType > ReturnTypes
Definition: WasmYAML.h:153
llvm::WasmYAML::CodeSection
Definition: WasmYAML.h:375
llvm::WasmYAML::NameEntry
Definition: WasmYAML.h:127
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:220
llvm::wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition: Wasm.h:317
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:146
llvm::raw_ostream::flush
void flush()
Definition: raw_ostream.h:186
llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:367
llvm::WasmYAML::SymbolInfo
Definition: WasmYAML.h:156
llvm::wasm::WASM_DYLINK_NEEDED
@ WASM_DYLINK_NEEDED
Definition: Wasm.h:353
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
llvm::wasm::WASM_SEC_DATA
@ WASM_SEC_DATA
Definition: Wasm.h:245
llvm::wasm::WASM_DYLINK_MEM_INFO
@ WASM_DYLINK_MEM_INFO
Definition: Wasm.h:352
Wasm.h
llvm::PassSummaryAction::Import
@ Import
Import information from summary.
llvm::WasmYAML::ExportSection
Definition: WasmYAML.h:345
llvm::wasm::WasmInitExpr::Float32
uint32_t Float32
Definition: Wasm.h:92
llvm::WasmYAML::Signature::Index
uint32_t Index
Definition: WasmYAML.h:150
llvm::WasmYAML::Section::Type
SectionType Type
Definition: WasmYAML.h:186
llvm::WasmYAML::SegmentInfo
Definition: WasmYAML.h:142
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLExtras.h:168
llvm::wasm::WASM_OPCODE_F64_CONST
@ WASM_OPCODE_F64_CONST
Definition: Wasm.h:285
llvm::wasm::WASM_EXTERNAL_TAG
@ WASM_EXTERNAL_TAG
Definition: Wasm.h:269
uint64_t
llvm::wasm::WASM_INIT_FUNCS
@ WASM_INIT_FUNCS
Definition: Wasm.h:345
llvm::WasmYAML::Signature::Form
SignatureForm Form
Definition: WasmYAML.h:151
llvm::wasm::WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition: Wasm.h:395
llvm::wasm::WASM_OPCODE_F32_CONST
@ WASM_OPCODE_F32_CONST
Definition: Wasm.h:284
LEB128.h
llvm::WasmYAML::StartSection
Definition: WasmYAML.h:355
llvm::wasm::ValType::FUNCREF
@ FUNCREF
llvm::WasmYAML::TargetFeaturesSection
Definition: WasmYAML.h:264
llvm::wasm::WASM_SYMBOL_TYPE_TAG
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:371
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::wasm::WASM_SYMBOL_TABLE
@ WASM_SYMBOL_TABLE
Definition: Wasm.h:347
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_OPCODE_I32_CONST
@ WASM_OPCODE_I32_CONST
Definition: Wasm.h:282
llvm::ARM::WinEH::ReturnType
ReturnType
Definition: ARMWinEH.h:25
llvm::wasm::WasmInitExpr::Int32
int32_t Int32
Definition: Wasm.h:90
yaml2obj.h
llvm::WasmYAML::Signature
Definition: WasmYAML.h:149
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::wasm::WASM_NAMES_GLOBAL
@ WASM_NAMES_GLOBAL
Definition: Wasm.h:338
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:136
uint32_t
llvm::yaml::yaml2wasm
bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
Definition: WasmEmitter.cpp:693
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::WasmYAML::Object
Definition: WasmYAML.h:405
llvm::WasmYAML::DataCountSection
Definition: WasmYAML.h:395
llvm::WasmYAML::TagSection
Definition: WasmYAML.h:325
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition: Wasm.h:316
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:145
llvm::WasmYAML::LinkingSection
Definition: WasmYAML.h:236
llvm::TargetStackID::Value
Value
Definition: TargetFrameLowering.h:27
llvm::wasm::WASM_EXTERNAL_FUNCTION
@ WASM_EXTERNAL_FUNCTION
Definition: Wasm.h:265
llvm::wasm::WasmInitExpr
Definition: Wasm.h:87
llvm::WasmYAML::NameEntry::Name
StringRef Name
Definition: WasmYAML.h:129
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:275
llvm::wasm::WASM_LIMITS_FLAG_HAS_MAX
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:310
llvm::WasmYAML::Signature::ParamTypes
std::vector< ValueType > ParamTypes
Definition: WasmYAML.h:152
llvm::wasm::WASM_EXTERNAL_GLOBAL
@ WASM_EXTERNAL_GLOBAL
Definition: Wasm.h:268
llvm::pdb::PDB_DataKind::Global
@ Global
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_NAMES_DATA_SEGMENT
@ WASM_NAMES_DATA_SEGMENT
Definition: Wasm.h:339
llvm::wasm::WasmInitExpr::Opcode
uint8_t Opcode
Definition: Wasm.h:88
llvm::wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition: Wasm.h:322
llvm::OptimizedStructLayoutField
A field in a structure.
Definition: OptimizedStructLayout.h:45
Endian.h
llvm::WasmYAML::ImportSection
Definition: WasmYAML.h:285
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::pdb::PDB_SymType::Export
@ Export
llvm::wasm::WASM_SYMBOL_TYPE_DATA
@ WASM_SYMBOL_TYPE_DATA
Definition: Wasm.h:368
llvm::wasm::WASM_SEC_CUSTOM
@ WASM_SEC_CUSTOM
Definition: Wasm.h:234
llvm::wasm::WASM_OPCODE_I64_CONST
@ WASM_OPCODE_I64_CONST
Definition: Wasm.h:283