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