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