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