1//===- WasmYAML.h - Wasm YAMLIO implementation ------------------*- C++ -*-===//
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/// This file declares classes for handling the YAML representation
11/// of wasm binaries.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_OBJECTYAML_WASMYAML_H
16#define LLVM_OBJECTYAML_WASMYAML_H
17
18#include "llvm/ADT/StringRef.h"
19#include "llvm/BinaryFormat/Wasm.h"
20#include "llvm/ObjectYAML/YAML.h"
21#include "llvm/Support/Casting.h"
22#include <cstdint>
23#include <memory>
24#include <vector>
25
26namespace llvm {
27namespace WasmYAML {
28
29LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionType)
30LLVM_YAML_STRONG_TYPEDEF(uint32_t, ValueType)
31LLVM_YAML_STRONG_TYPEDEF(uint32_t, TableType)
32LLVM_YAML_STRONG_TYPEDEF(uint32_t, SignatureForm)
33LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportKind)
34LLVM_YAML_STRONG_TYPEDEF(uint32_t, Opcode)
35LLVM_YAML_STRONG_TYPEDEF(uint32_t, RelocType)
36LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolFlags)
37LLVM_YAML_STRONG_TYPEDEF(uint32_t, SymbolKind)
38LLVM_YAML_STRONG_TYPEDEF(uint32_t, SegmentFlags)
39LLVM_YAML_STRONG_TYPEDEF(uint32_t, LimitFlags)
40LLVM_YAML_STRONG_TYPEDEF(uint32_t, ComdatKind)
41LLVM_YAML_STRONG_TYPEDEF(uint32_t, FeaturePolicyPrefix)
42
43struct FileHeader {
44  yaml::Hex32 Version;
45};
46
47struct Limits {
48  LimitFlags Flags;
49  yaml::Hex32 Minimum;
50  yaml::Hex32 Maximum;
51};
52
53struct Table {
54  TableType ElemType;
55  Limits TableLimits;
56  uint32_t Index;
57};
58
59struct Export {
60  StringRef Name;
61  ExportKind Kind;
62  uint32_t Index;
63};
64
65struct InitExpr {
66  InitExpr() {}
67  bool Extended;
68  union {
69    wasm::WasmInitExprMVP Inst;
70    yaml::BinaryRef Body;
71  };
72};
73
74struct ElemSegment {
75  uint32_t Flags;
76  uint32_t TableNumber;
77  ValueType ElemKind;
78  InitExpr Offset;
79  std::vector<uint32_t> Functions;
80};
81
82struct Global {
83  uint32_t Index;
84  ValueType Type;
85  bool Mutable;
86  InitExpr Init;
87};
88
89struct Import {
90  Import() {}
91  StringRef Module;
92  StringRef Field;
93  ExportKind Kind;
94  union {
95    uint32_t SigIndex;
96    Table TableImport;
97    Limits Memory;
98    uint32_t TagIndex;
99    Global GlobalImport;
100  };
101};
102
103struct LocalDecl {
104  ValueType Type;
105  uint32_t Count;
106};
107
108struct Function {
109  uint32_t Index;
110  std::vector<LocalDecl> Locals;
111  yaml::BinaryRef Body;
112};
113
114struct Relocation {
115  RelocType Type;
116  uint32_t Index;
117  // TODO(wvo): this would strictly be better as Hex64, but that will change
118  // all existing obj2yaml output.
119  yaml::Hex32 Offset;
120  int64_t Addend;
121};
122
123struct DataSegment {
124  uint32_t SectionOffset;
125  uint32_t InitFlags;
126  uint32_t MemoryIndex;
127  InitExpr Offset;
128  yaml::BinaryRef Content;
129};
130
131struct NameEntry {
132  uint32_t Index;
133  StringRef Name;
134};
135
136struct ProducerEntry {
137  std::string Name;
138  std::string Version;
139};
140
141struct FeatureEntry {
142  FeaturePolicyPrefix Prefix;
143  std::string Name;
144};
145
146struct SegmentInfo {
147  uint32_t Index;
148  StringRef Name;
149  uint32_t Alignment;
150  SegmentFlags Flags;
151};
152
153struct Signature {
154  uint32_t Index;
155  SignatureForm Form = wasm::WASM_TYPE_FUNC;
156  std::vector<ValueType> ParamTypes;
157  std::vector<ValueType> ReturnTypes;
158};
159
160struct SymbolInfo {
161  uint32_t Index;
162  StringRef Name;
163  SymbolKind Kind;
164  SymbolFlags Flags;
165  union {
166    uint32_t ElementIndex;
167    wasm::WasmDataReference DataRef;
168  };
169};
170
171struct InitFunction {
172  uint32_t Priority;
173  uint32_t Symbol;
174};
175
176struct ComdatEntry {
177  ComdatKind Kind;
178  uint32_t Index;
179};
180
181struct Comdat {
182  StringRef Name;
183  std::vector<ComdatEntry> Entries;
184};
185
186struct Section {
187  explicit Section(SectionType SecType) : Type(SecType) {}
188  virtual ~Section();
189
190  SectionType Type;
191  std::vector<Relocation> Relocations;
192  std::optional<uint8_t> HeaderSecSizeEncodingLen;
193};
194
195struct CustomSection : Section {
196  explicit CustomSection(StringRef Name)
197      : Section(wasm::WASM_SEC_CUSTOM), Name(Name) {}
198
199  static bool classof(const Section *S) {
200    return S->Type == wasm::WASM_SEC_CUSTOM;
201  }
202
203  StringRef Name;
204  yaml::BinaryRef Payload;
205};
206
207struct DylinkImportInfo {
208  StringRef Module;
209  StringRef Field;
210  SymbolFlags Flags;
211};
212
213struct DylinkExportInfo {
214  StringRef Name;
215  SymbolFlags Flags;
216};
217
218struct DylinkSection : CustomSection {
219  DylinkSection() : CustomSection("dylink.0") {}
220
221  static bool classof(const Section *S) {
222    auto C = dyn_cast<CustomSection>(S);
223    return C && C->Name == "dylink.0";
224  }
225
226  uint32_t MemorySize;
227  uint32_t MemoryAlignment;
228  uint32_t TableSize;
229  uint32_t TableAlignment;
230  std::vector<StringRef> Needed;
231  std::vector<DylinkImportInfo> ImportInfo;
232  std::vector<DylinkExportInfo> ExportInfo;
233};
234
235struct NameSection : CustomSection {
236  NameSection() : CustomSection("name") {}
237
238  static bool classof(const Section *S) {
239    auto C = dyn_cast<CustomSection>(S);
240    return C && C->Name == "name";
241  }
242
243  std::vector<NameEntry> FunctionNames;
244  std::vector<NameEntry> GlobalNames;
245  std::vector<NameEntry> DataSegmentNames;
246};
247
248struct LinkingSection : CustomSection {
249  LinkingSection() : CustomSection("linking") {}
250
251  static bool classof(const Section *S) {
252    auto C = dyn_cast<CustomSection>(S);
253    return C && C->Name == "linking";
254  }
255
256  uint32_t Version;
257  std::vector<SymbolInfo> SymbolTable;
258  std::vector<SegmentInfo> SegmentInfos;
259  std::vector<InitFunction> InitFunctions;
260  std::vector<Comdat> Comdats;
261};
262
263struct ProducersSection : CustomSection {
264  ProducersSection() : CustomSection("producers") {}
265
266  static bool classof(const Section *S) {
267    auto C = dyn_cast<CustomSection>(S);
268    return C && C->Name == "producers";
269  }
270
271  std::vector<ProducerEntry> Languages;
272  std::vector<ProducerEntry> Tools;
273  std::vector<ProducerEntry> SDKs;
274};
275
276struct TargetFeaturesSection : CustomSection {
277  TargetFeaturesSection() : CustomSection("target_features") {}
278
279  static bool classof(const Section *S) {
280    auto C = dyn_cast<CustomSection>(S);
281    return C && C->Name == "target_features";
282  }
283
284  std::vector<FeatureEntry> Features;
285};
286
287struct TypeSection : Section {
288  TypeSection() : Section(wasm::WASM_SEC_TYPE) {}
289
290  static bool classof(const Section *S) {
291    return S->Type == wasm::WASM_SEC_TYPE;
292  }
293
294  std::vector<Signature> Signatures;
295};
296
297struct ImportSection : Section {
298  ImportSection() : Section(wasm::WASM_SEC_IMPORT) {}
299
300  static bool classof(const Section *S) {
301    return S->Type == wasm::WASM_SEC_IMPORT;
302  }
303
304  std::vector<Import> Imports;
305};
306
307struct FunctionSection : Section {
308  FunctionSection() : Section(wasm::WASM_SEC_FUNCTION) {}
309
310  static bool classof(const Section *S) {
311    return S->Type == wasm::WASM_SEC_FUNCTION;
312  }
313
314  std::vector<uint32_t> FunctionTypes;
315};
316
317struct TableSection : Section {
318  TableSection() : Section(wasm::WASM_SEC_TABLE) {}
319
320  static bool classof(const Section *S) {
321    return S->Type == wasm::WASM_SEC_TABLE;
322  }
323
324  std::vector<Table> Tables;
325};
326
327struct MemorySection : Section {
328  MemorySection() : Section(wasm::WASM_SEC_MEMORY) {}
329
330  static bool classof(const Section *S) {
331    return S->Type == wasm::WASM_SEC_MEMORY;
332  }
333
334  std::vector<Limits> Memories;
335};
336
337struct TagSection : Section {
338  TagSection() : Section(wasm::WASM_SEC_TAG) {}
339
340  static bool classof(const Section *S) {
341    return S->Type == wasm::WASM_SEC_TAG;
342  }
343
344  std::vector<uint32_t> TagTypes;
345};
346
347struct GlobalSection : Section {
348  GlobalSection() : Section(wasm::WASM_SEC_GLOBAL) {}
349
350  static bool classof(const Section *S) {
351    return S->Type == wasm::WASM_SEC_GLOBAL;
352  }
353
354  std::vector<Global> Globals;
355};
356
357struct ExportSection : Section {
358  ExportSection() : Section(wasm::WASM_SEC_EXPORT) {}
359
360  static bool classof(const Section *S) {
361    return S->Type == wasm::WASM_SEC_EXPORT;
362  }
363
364  std::vector<Export> Exports;
365};
366
367struct StartSection : Section {
368  StartSection() : Section(wasm::WASM_SEC_START) {}
369
370  static bool classof(const Section *S) {
371    return S->Type == wasm::WASM_SEC_START;
372  }
373
374  uint32_t StartFunction;
375};
376
377struct ElemSection : Section {
378  ElemSection() : Section(wasm::WASM_SEC_ELEM) {}
379
380  static bool classof(const Section *S) {
381    return S->Type == wasm::WASM_SEC_ELEM;
382  }
383
384  std::vector<ElemSegment> Segments;
385};
386
387struct CodeSection : Section {
388  CodeSection() : Section(wasm::WASM_SEC_CODE) {}
389
390  static bool classof(const Section *S) {
391    return S->Type == wasm::WASM_SEC_CODE;
392  }
393
394  std::vector<Function> Functions;
395};
396
397struct DataSection : Section {
398  DataSection() : Section(wasm::WASM_SEC_DATA) {}
399
400  static bool classof(const Section *S) {
401    return S->Type == wasm::WASM_SEC_DATA;
402  }
403
404  std::vector<DataSegment> Segments;
405};
406
407struct DataCountSection : Section {
408  DataCountSection() : Section(wasm::WASM_SEC_DATACOUNT) {}
409
410  static bool classof(const Section *S) {
411    return S->Type == wasm::WASM_SEC_DATACOUNT;
412  }
413
414  uint32_t Count;
415};
416
417struct Object {
418  FileHeader Header;
419  std::vector<std::unique_ptr<Section>> Sections;
420};
421
422} // end namespace WasmYAML
423} // end namespace llvm
424
425LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<llvm::WasmYAML::Section>)
426LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Signature)
427LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ValueType)
428LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Table)
429LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Import)
430LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Export)
431LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ElemSegment)
432LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Limits)
433LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DataSegment)
434LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Global)
435LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Function)
436LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::LocalDecl)
437LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Relocation)
438LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::NameEntry)
439LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ProducerEntry)
440LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::FeatureEntry)
441LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SegmentInfo)
442LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::SymbolInfo)
443LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::InitFunction)
444LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::ComdatEntry)
445LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::Comdat)
446LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkImportInfo)
447LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::WasmYAML::DylinkExportInfo)
448
449namespace llvm {
450namespace yaml {
451
452template <> struct MappingTraits<WasmYAML::FileHeader> {
453  static void mapping(IO &IO, WasmYAML::FileHeader &FileHdr);
454};
455
456template <> struct MappingTraits<std::unique_ptr<WasmYAML::Section>> {
457  static void mapping(IO &IO, std::unique_ptr<WasmYAML::Section> &Section);
458};
459
460template <> struct MappingTraits<WasmYAML::Object> {
461  static void mapping(IO &IO, WasmYAML::Object &Object);
462};
463
464template <> struct MappingTraits<WasmYAML::Import> {
465  static void mapping(IO &IO, WasmYAML::Import &Import);
466};
467
468template <> struct MappingTraits<WasmYAML::Export> {
469  static void mapping(IO &IO, WasmYAML::Export &Export);
470};
471
472template <> struct MappingTraits<WasmYAML::Global> {
473  static void mapping(IO &IO, WasmYAML::Global &Global);
474};
475
476template <> struct ScalarBitSetTraits<WasmYAML::LimitFlags> {
477  static void bitset(IO &IO, WasmYAML::LimitFlags &Value);
478};
479
480template <> struct ScalarBitSetTraits<WasmYAML::SymbolFlags> {
481  static void bitset(IO &IO, WasmYAML::SymbolFlags &Value);
482};
483
484template <> struct ScalarEnumerationTraits<WasmYAML::SymbolKind> {
485  static void enumeration(IO &IO, WasmYAML::SymbolKind &Kind);
486};
487
488template <> struct ScalarBitSetTraits<WasmYAML::SegmentFlags> {
489  static void bitset(IO &IO, WasmYAML::SegmentFlags &Value);
490};
491
492template <> struct ScalarEnumerationTraits<WasmYAML::SectionType> {
493  static void enumeration(IO &IO, WasmYAML::SectionType &Type);
494};
495
496template <> struct MappingTraits<WasmYAML::Signature> {
497  static void mapping(IO &IO, WasmYAML::Signature &Signature);
498};
499
500template <> struct MappingTraits<WasmYAML::Table> {
501  static void mapping(IO &IO, WasmYAML::Table &Table);
502};
503
504template <> struct MappingTraits<WasmYAML::Limits> {
505  static void mapping(IO &IO, WasmYAML::Limits &Limits);
506};
507
508template <> struct MappingTraits<WasmYAML::Function> {
509  static void mapping(IO &IO, WasmYAML::Function &Function);
510};
511
512template <> struct MappingTraits<WasmYAML::Relocation> {
513  static void mapping(IO &IO, WasmYAML::Relocation &Relocation);
514};
515
516template <> struct MappingTraits<WasmYAML::NameEntry> {
517  static void mapping(IO &IO, WasmYAML::NameEntry &NameEntry);
518};
519
520template <> struct MappingTraits<WasmYAML::ProducerEntry> {
521  static void mapping(IO &IO, WasmYAML::ProducerEntry &ProducerEntry);
522};
523
524template <> struct ScalarEnumerationTraits<WasmYAML::FeaturePolicyPrefix> {
525  static void enumeration(IO &IO, WasmYAML::FeaturePolicyPrefix &Prefix);
526};
527
528template <> struct MappingTraits<WasmYAML::FeatureEntry> {
529  static void mapping(IO &IO, WasmYAML::FeatureEntry &FeatureEntry);
530};
531
532template <> struct MappingTraits<WasmYAML::SegmentInfo> {
533  static void mapping(IO &IO, WasmYAML::SegmentInfo &SegmentInfo);
534};
535
536template <> struct MappingTraits<WasmYAML::LocalDecl> {
537  static void mapping(IO &IO, WasmYAML::LocalDecl &LocalDecl);
538};
539
540template <> struct MappingTraits<WasmYAML::InitExpr> {
541  static void mapping(IO &IO, WasmYAML::InitExpr &Expr);
542};
543
544template <> struct MappingTraits<WasmYAML::DataSegment> {
545  static void mapping(IO &IO, WasmYAML::DataSegment &Segment);
546};
547
548template <> struct MappingTraits<WasmYAML::ElemSegment> {
549  static void mapping(IO &IO, WasmYAML::ElemSegment &Segment);
550};
551
552template <> struct MappingTraits<WasmYAML::SymbolInfo> {
553  static void mapping(IO &IO, WasmYAML::SymbolInfo &Info);
554};
555
556template <> struct MappingTraits<WasmYAML::InitFunction> {
557  static void mapping(IO &IO, WasmYAML::InitFunction &Init);
558};
559
560template <> struct ScalarEnumerationTraits<WasmYAML::ComdatKind> {
561  static void enumeration(IO &IO, WasmYAML::ComdatKind &Kind);
562};
563
564template <> struct MappingTraits<WasmYAML::ComdatEntry> {
565  static void mapping(IO &IO, WasmYAML::ComdatEntry &ComdatEntry);
566};
567
568template <> struct MappingTraits<WasmYAML::Comdat> {
569  static void mapping(IO &IO, WasmYAML::Comdat &Comdat);
570};
571
572template <> struct ScalarEnumerationTraits<WasmYAML::ValueType> {
573  static void enumeration(IO &IO, WasmYAML::ValueType &Type);
574};
575
576template <> struct ScalarEnumerationTraits<WasmYAML::ExportKind> {
577  static void enumeration(IO &IO, WasmYAML::ExportKind &Kind);
578};
579
580template <> struct ScalarEnumerationTraits<WasmYAML::TableType> {
581  static void enumeration(IO &IO, WasmYAML::TableType &Type);
582};
583
584template <> struct ScalarEnumerationTraits<WasmYAML::Opcode> {
585  static void enumeration(IO &IO, WasmYAML::Opcode &Opcode);
586};
587
588template <> struct ScalarEnumerationTraits<WasmYAML::RelocType> {
589  static void enumeration(IO &IO, WasmYAML::RelocType &Kind);
590};
591
592template <> struct MappingTraits<WasmYAML::DylinkImportInfo> {
593  static void mapping(IO &IO, WasmYAML::DylinkImportInfo &Info);
594};
595
596template <> struct MappingTraits<WasmYAML::DylinkExportInfo> {
597  static void mapping(IO &IO, WasmYAML::DylinkExportInfo &Info);
598};
599
600} // end namespace yaml
601} // end namespace llvm
602
603#endif // LLVM_OBJECTYAML_WASMYAML_H
604