1 //===- WasmYAML.cpp - Wasm YAMLIO implementation --------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines classes for handling the YAML representation of wasm.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ObjectYAML/WasmYAML.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Support/Casting.h"
17 #include "llvm/Support/ErrorHandling.h"
18 #include "llvm/Support/YAMLTraits.h"
19 
20 namespace llvm {
21 
22 namespace WasmYAML {
23 
24 // Declared here rather than in the header to comply with:
25 // http://llvm.org/docs/CodingStandards.html#provide-a-virtual-method-anchor-for-classes-in-headers
26 Section::~Section() = default;
27 
28 } // end namespace WasmYAML
29 
30 namespace yaml {
31 
32 void MappingTraits<WasmYAML::FileHeader>::mapping(
33     IO &IO, WasmYAML::FileHeader &FileHdr) {
34   IO.mapRequired("Version", FileHdr.Version);
35 }
36 
37 void MappingTraits<WasmYAML::Object>::mapping(IO &IO,
38                                               WasmYAML::Object &Object) {
39   IO.setContext(&Object);
40   IO.mapTag("!WASM", true);
41   IO.mapRequired("FileHeader", Object.Header);
42   IO.mapOptional("Sections", Object.Sections);
43   IO.setContext(nullptr);
44 }
45 
46 static void commonSectionMapping(IO &IO, WasmYAML::Section &Section) {
47   IO.mapRequired("Type", Section.Type);
48   IO.mapOptional("Relocations", Section.Relocations);
49 }
50 
51 static void sectionMapping(IO &IO, WasmYAML::DylinkSection &Section) {
52   commonSectionMapping(IO, Section);
53   IO.mapRequired("Name", Section.Name);
54   IO.mapRequired("MemorySize", Section.MemorySize);
55   IO.mapRequired("MemoryAlignment", Section.MemoryAlignment);
56   IO.mapRequired("TableSize", Section.TableSize);
57   IO.mapRequired("TableAlignment", Section.TableAlignment);
58 }
59 
60 static void sectionMapping(IO &IO, WasmYAML::NameSection &Section) {
61   commonSectionMapping(IO, Section);
62   IO.mapRequired("Name", Section.Name);
63   IO.mapOptional("FunctionNames", Section.FunctionNames);
64 }
65 
66 static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
67   commonSectionMapping(IO, Section);
68   IO.mapRequired("Name", Section.Name);
69   IO.mapRequired("Version", Section.Version);
70   IO.mapOptional("SymbolTable", Section.SymbolTable);
71   IO.mapOptional("SegmentInfo", Section.SegmentInfos);
72   IO.mapOptional("InitFunctions", Section.InitFunctions);
73   IO.mapOptional("Comdats", Section.Comdats);
74 }
75 
76 static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
77   commonSectionMapping(IO, Section);
78   IO.mapRequired("Name", Section.Name);
79   IO.mapRequired("Payload", Section.Payload);
80 }
81 
82 static void sectionMapping(IO &IO, WasmYAML::TypeSection &Section) {
83   commonSectionMapping(IO, Section);
84   IO.mapOptional("Signatures", Section.Signatures);
85 }
86 
87 static void sectionMapping(IO &IO, WasmYAML::ImportSection &Section) {
88   commonSectionMapping(IO, Section);
89   IO.mapOptional("Imports", Section.Imports);
90 }
91 
92 static void sectionMapping(IO &IO, WasmYAML::FunctionSection &Section) {
93   commonSectionMapping(IO, Section);
94   IO.mapOptional("FunctionTypes", Section.FunctionTypes);
95 }
96 
97 static void sectionMapping(IO &IO, WasmYAML::TableSection &Section) {
98   commonSectionMapping(IO, Section);
99   IO.mapOptional("Tables", Section.Tables);
100 }
101 
102 static void sectionMapping(IO &IO, WasmYAML::MemorySection &Section) {
103   commonSectionMapping(IO, Section);
104   IO.mapOptional("Memories", Section.Memories);
105 }
106 
107 static void sectionMapping(IO &IO, WasmYAML::GlobalSection &Section) {
108   commonSectionMapping(IO, Section);
109   IO.mapOptional("Globals", Section.Globals);
110 }
111 
112 static void sectionMapping(IO &IO, WasmYAML::EventSection &Section) {
113   commonSectionMapping(IO, Section);
114   IO.mapOptional("Events", Section.Events);
115 }
116 
117 static void sectionMapping(IO &IO, WasmYAML::ExportSection &Section) {
118   commonSectionMapping(IO, Section);
119   IO.mapOptional("Exports", Section.Exports);
120 }
121 
122 static void sectionMapping(IO &IO, WasmYAML::StartSection &Section) {
123   commonSectionMapping(IO, Section);
124   IO.mapOptional("StartFunction", Section.StartFunction);
125 }
126 
127 static void sectionMapping(IO &IO, WasmYAML::ElemSection &Section) {
128   commonSectionMapping(IO, Section);
129   IO.mapOptional("Segments", Section.Segments);
130 }
131 
132 static void sectionMapping(IO &IO, WasmYAML::CodeSection &Section) {
133   commonSectionMapping(IO, Section);
134   IO.mapRequired("Functions", Section.Functions);
135 }
136 
137 static void sectionMapping(IO &IO, WasmYAML::DataSection &Section) {
138   commonSectionMapping(IO, Section);
139   IO.mapRequired("Segments", Section.Segments);
140 }
141 
142 void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping(
143     IO &IO, std::unique_ptr<WasmYAML::Section> &Section) {
144   WasmYAML::SectionType SectionType;
145   if (IO.outputting())
146     SectionType = Section->Type;
147   else
148     IO.mapRequired("Type", SectionType);
149 
150   switch (SectionType) {
151   case wasm::WASM_SEC_CUSTOM: {
152     StringRef SectionName;
153     if (IO.outputting()) {
154       auto CustomSection = cast<WasmYAML::CustomSection>(Section.get());
155       SectionName = CustomSection->Name;
156     } else {
157       IO.mapRequired("Name", SectionName);
158     }
159     if (SectionName == "dylink") {
160       if (!IO.outputting())
161         Section.reset(new WasmYAML::DylinkSection());
162       sectionMapping(IO, *cast<WasmYAML::DylinkSection>(Section.get()));
163     } else if (SectionName == "linking") {
164       if (!IO.outputting())
165         Section.reset(new WasmYAML::LinkingSection());
166       sectionMapping(IO, *cast<WasmYAML::LinkingSection>(Section.get()));
167     } else if (SectionName == "name") {
168       if (!IO.outputting())
169         Section.reset(new WasmYAML::NameSection());
170       sectionMapping(IO, *cast<WasmYAML::NameSection>(Section.get()));
171     } else {
172       if (!IO.outputting())
173         Section.reset(new WasmYAML::CustomSection(SectionName));
174       sectionMapping(IO, *cast<WasmYAML::CustomSection>(Section.get()));
175     }
176     break;
177   }
178   case wasm::WASM_SEC_TYPE:
179     if (!IO.outputting())
180       Section.reset(new WasmYAML::TypeSection());
181     sectionMapping(IO, *cast<WasmYAML::TypeSection>(Section.get()));
182     break;
183   case wasm::WASM_SEC_IMPORT:
184     if (!IO.outputting())
185       Section.reset(new WasmYAML::ImportSection());
186     sectionMapping(IO, *cast<WasmYAML::ImportSection>(Section.get()));
187     break;
188   case wasm::WASM_SEC_FUNCTION:
189     if (!IO.outputting())
190       Section.reset(new WasmYAML::FunctionSection());
191     sectionMapping(IO, *cast<WasmYAML::FunctionSection>(Section.get()));
192     break;
193   case wasm::WASM_SEC_TABLE:
194     if (!IO.outputting())
195       Section.reset(new WasmYAML::TableSection());
196     sectionMapping(IO, *cast<WasmYAML::TableSection>(Section.get()));
197     break;
198   case wasm::WASM_SEC_MEMORY:
199     if (!IO.outputting())
200       Section.reset(new WasmYAML::MemorySection());
201     sectionMapping(IO, *cast<WasmYAML::MemorySection>(Section.get()));
202     break;
203   case wasm::WASM_SEC_GLOBAL:
204     if (!IO.outputting())
205       Section.reset(new WasmYAML::GlobalSection());
206     sectionMapping(IO, *cast<WasmYAML::GlobalSection>(Section.get()));
207     break;
208   case wasm::WASM_SEC_EVENT:
209     if (!IO.outputting())
210       Section.reset(new WasmYAML::EventSection());
211     sectionMapping(IO, *cast<WasmYAML::EventSection>(Section.get()));
212     break;
213   case wasm::WASM_SEC_EXPORT:
214     if (!IO.outputting())
215       Section.reset(new WasmYAML::ExportSection());
216     sectionMapping(IO, *cast<WasmYAML::ExportSection>(Section.get()));
217     break;
218   case wasm::WASM_SEC_START:
219     if (!IO.outputting())
220       Section.reset(new WasmYAML::StartSection());
221     sectionMapping(IO, *cast<WasmYAML::StartSection>(Section.get()));
222     break;
223   case wasm::WASM_SEC_ELEM:
224     if (!IO.outputting())
225       Section.reset(new WasmYAML::ElemSection());
226     sectionMapping(IO, *cast<WasmYAML::ElemSection>(Section.get()));
227     break;
228   case wasm::WASM_SEC_CODE:
229     if (!IO.outputting())
230       Section.reset(new WasmYAML::CodeSection());
231     sectionMapping(IO, *cast<WasmYAML::CodeSection>(Section.get()));
232     break;
233   case wasm::WASM_SEC_DATA:
234     if (!IO.outputting())
235       Section.reset(new WasmYAML::DataSection());
236     sectionMapping(IO, *cast<WasmYAML::DataSection>(Section.get()));
237     break;
238   default:
239     llvm_unreachable("Unknown section type");
240   }
241 }
242 
243 void ScalarEnumerationTraits<WasmYAML::SectionType>::enumeration(
244     IO &IO, WasmYAML::SectionType &Type) {
245 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_SEC_##X);
246   ECase(CUSTOM);
247   ECase(TYPE);
248   ECase(IMPORT);
249   ECase(FUNCTION);
250   ECase(TABLE);
251   ECase(MEMORY);
252   ECase(GLOBAL);
253   ECase(EVENT);
254   ECase(EXPORT);
255   ECase(START);
256   ECase(ELEM);
257   ECase(CODE);
258   ECase(DATA);
259 #undef ECase
260 }
261 
262 void MappingTraits<WasmYAML::Signature>::mapping(
263     IO &IO, WasmYAML::Signature &Signature) {
264   IO.mapRequired("Index", Signature.Index);
265   IO.mapRequired("ReturnType", Signature.ReturnType);
266   IO.mapRequired("ParamTypes", Signature.ParamTypes);
267 }
268 
269 void MappingTraits<WasmYAML::Table>::mapping(IO &IO, WasmYAML::Table &Table) {
270   IO.mapRequired("ElemType", Table.ElemType);
271   IO.mapRequired("Limits", Table.TableLimits);
272 }
273 
274 void MappingTraits<WasmYAML::Function>::mapping(IO &IO,
275                                                 WasmYAML::Function &Function) {
276   IO.mapRequired("Index", Function.Index);
277   IO.mapRequired("Locals", Function.Locals);
278   IO.mapRequired("Body", Function.Body);
279 }
280 
281 void MappingTraits<WasmYAML::Relocation>::mapping(
282     IO &IO, WasmYAML::Relocation &Relocation) {
283   IO.mapRequired("Type", Relocation.Type);
284   IO.mapRequired("Index", Relocation.Index);
285   IO.mapRequired("Offset", Relocation.Offset);
286   IO.mapOptional("Addend", Relocation.Addend, 0);
287 }
288 
289 void MappingTraits<WasmYAML::NameEntry>::mapping(
290     IO &IO, WasmYAML::NameEntry &NameEntry) {
291   IO.mapRequired("Index", NameEntry.Index);
292   IO.mapRequired("Name", NameEntry.Name);
293 }
294 
295 void MappingTraits<WasmYAML::SegmentInfo>::mapping(
296     IO &IO, WasmYAML::SegmentInfo &SegmentInfo) {
297   IO.mapRequired("Index", SegmentInfo.Index);
298   IO.mapRequired("Name", SegmentInfo.Name);
299   IO.mapRequired("Alignment", SegmentInfo.Alignment);
300   IO.mapRequired("Flags", SegmentInfo.Flags);
301 }
302 
303 void MappingTraits<WasmYAML::LocalDecl>::mapping(
304     IO &IO, WasmYAML::LocalDecl &LocalDecl) {
305   IO.mapRequired("Type", LocalDecl.Type);
306   IO.mapRequired("Count", LocalDecl.Count);
307 }
308 
309 void MappingTraits<WasmYAML::Limits>::mapping(IO &IO,
310                                               WasmYAML::Limits &Limits) {
311   if (!IO.outputting() || Limits.Flags)
312     IO.mapOptional("Flags", Limits.Flags);
313   IO.mapRequired("Initial", Limits.Initial);
314   if (!IO.outputting() || Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
315     IO.mapOptional("Maximum", Limits.Maximum);
316 }
317 
318 void MappingTraits<WasmYAML::ElemSegment>::mapping(
319     IO &IO, WasmYAML::ElemSegment &Segment) {
320   IO.mapRequired("Offset", Segment.Offset);
321   IO.mapRequired("Functions", Segment.Functions);
322 }
323 
324 void MappingTraits<WasmYAML::Import>::mapping(IO &IO,
325                                               WasmYAML::Import &Import) {
326   IO.mapRequired("Module", Import.Module);
327   IO.mapRequired("Field", Import.Field);
328   IO.mapRequired("Kind", Import.Kind);
329   if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
330     IO.mapRequired("SigIndex", Import.SigIndex);
331   } else if (Import.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
332     IO.mapRequired("GlobalType", Import.GlobalImport.Type);
333     IO.mapRequired("GlobalMutable", Import.GlobalImport.Mutable);
334   } else if (Import.Kind == wasm::WASM_EXTERNAL_EVENT) {
335     IO.mapRequired("EventAttribute", Import.EventImport.Attribute);
336     IO.mapRequired("EventSigIndex", Import.EventImport.SigIndex);
337   } else if (Import.Kind == wasm::WASM_EXTERNAL_TABLE) {
338     IO.mapRequired("Table", Import.TableImport);
339   } else if (Import.Kind == wasm::WASM_EXTERNAL_MEMORY) {
340     IO.mapRequired("Memory", Import.Memory);
341   } else {
342     llvm_unreachable("unhandled import type");
343   }
344 }
345 
346 void MappingTraits<WasmYAML::Export>::mapping(IO &IO,
347                                               WasmYAML::Export &Export) {
348   IO.mapRequired("Name", Export.Name);
349   IO.mapRequired("Kind", Export.Kind);
350   IO.mapRequired("Index", Export.Index);
351 }
352 
353 void MappingTraits<WasmYAML::Global>::mapping(IO &IO,
354                                               WasmYAML::Global &Global) {
355   IO.mapRequired("Index", Global.Index);
356   IO.mapRequired("Type", Global.Type);
357   IO.mapRequired("Mutable", Global.Mutable);
358   IO.mapRequired("InitExpr", Global.InitExpr);
359 }
360 
361 void MappingTraits<wasm::WasmInitExpr>::mapping(IO &IO,
362                                                 wasm::WasmInitExpr &Expr) {
363   WasmYAML::Opcode Op = Expr.Opcode;
364   IO.mapRequired("Opcode", Op);
365   Expr.Opcode = Op;
366   switch (Expr.Opcode) {
367   case wasm::WASM_OPCODE_I32_CONST:
368     IO.mapRequired("Value", Expr.Value.Int32);
369     break;
370   case wasm::WASM_OPCODE_I64_CONST:
371     IO.mapRequired("Value", Expr.Value.Int64);
372     break;
373   case wasm::WASM_OPCODE_F32_CONST:
374     IO.mapRequired("Value", Expr.Value.Float32);
375     break;
376   case wasm::WASM_OPCODE_F64_CONST:
377     IO.mapRequired("Value", Expr.Value.Float64);
378     break;
379   case wasm::WASM_OPCODE_GET_GLOBAL:
380     IO.mapRequired("Index", Expr.Value.Global);
381     break;
382   }
383 }
384 
385 void MappingTraits<WasmYAML::DataSegment>::mapping(
386     IO &IO, WasmYAML::DataSegment &Segment) {
387   IO.mapOptional("SectionOffset", Segment.SectionOffset);
388   IO.mapRequired("MemoryIndex", Segment.MemoryIndex);
389   IO.mapRequired("Offset", Segment.Offset);
390   IO.mapRequired("Content", Segment.Content);
391 }
392 
393 void MappingTraits<WasmYAML::InitFunction>::mapping(
394     IO &IO, WasmYAML::InitFunction &Init) {
395   IO.mapRequired("Priority", Init.Priority);
396   IO.mapRequired("Symbol", Init.Symbol);
397 }
398 
399 void ScalarEnumerationTraits<WasmYAML::ComdatKind>::enumeration(
400     IO &IO, WasmYAML::ComdatKind &Kind) {
401 #define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_COMDAT_##X);
402   ECase(FUNCTION);
403   ECase(DATA);
404 #undef ECase
405 }
406 
407 void MappingTraits<WasmYAML::ComdatEntry>::mapping(
408     IO &IO, WasmYAML::ComdatEntry &ComdatEntry) {
409   IO.mapRequired("Kind", ComdatEntry.Kind);
410   IO.mapRequired("Index", ComdatEntry.Index);
411 }
412 
413 void MappingTraits<WasmYAML::Comdat>::mapping(IO &IO,
414                                               WasmYAML::Comdat &Comdat) {
415   IO.mapRequired("Name", Comdat.Name);
416   IO.mapRequired("Entries", Comdat.Entries);
417 }
418 
419 void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
420                                                   WasmYAML::SymbolInfo &Info) {
421   IO.mapRequired("Index", Info.Index);
422   IO.mapRequired("Kind", Info.Kind);
423   IO.mapRequired("Name", Info.Name);
424   IO.mapRequired("Flags", Info.Flags);
425   if (Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION) {
426     IO.mapRequired("Function", Info.ElementIndex);
427   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL) {
428     IO.mapRequired("Global", Info.ElementIndex);
429   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT) {
430     IO.mapRequired("Event", Info.ElementIndex);
431   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA) {
432     if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
433       IO.mapRequired("Segment", Info.DataRef.Segment);
434       IO.mapOptional("Offset", Info.DataRef.Offset, 0u);
435       IO.mapRequired("Size", Info.DataRef.Size);
436     }
437   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_SECTION) {
438     IO.mapRequired("Section", Info.ElementIndex);
439   } else {
440     llvm_unreachable("unsupported symbol kind");
441   }
442 }
443 
444 void MappingTraits<WasmYAML::Event>::mapping(IO &IO, WasmYAML::Event &Event) {
445   IO.mapRequired("Index", Event.Index);
446   IO.mapRequired("Attribute", Event.Attribute);
447   IO.mapRequired("SigIndex", Event.SigIndex);
448 }
449 
450 void ScalarBitSetTraits<WasmYAML::LimitFlags>::bitset(
451     IO &IO, WasmYAML::LimitFlags &Value) {
452 #define BCase(X) IO.bitSetCase(Value, #X, wasm::WASM_LIMITS_FLAG_##X)
453   BCase(HAS_MAX);
454   BCase(IS_SHARED);
455 #undef BCase
456 }
457 
458 void ScalarBitSetTraits<WasmYAML::SegmentFlags>::bitset(
459     IO &IO, WasmYAML::SegmentFlags &Value) {}
460 
461 void ScalarBitSetTraits<WasmYAML::SymbolFlags>::bitset(
462     IO &IO, WasmYAML::SymbolFlags &Value) {
463 #define BCaseMask(M, X)                                                        \
464   IO.maskedBitSetCase(Value, #X, wasm::WASM_SYMBOL_##X, wasm::WASM_SYMBOL_##M)
465   // BCaseMask(BINDING_MASK, BINDING_GLOBAL);
466   BCaseMask(BINDING_MASK, BINDING_WEAK);
467   BCaseMask(BINDING_MASK, BINDING_LOCAL);
468   // BCaseMask(VISIBILITY_MASK, VISIBILITY_DEFAULT);
469   BCaseMask(VISIBILITY_MASK, VISIBILITY_HIDDEN);
470   BCaseMask(UNDEFINED, UNDEFINED);
471 #undef BCaseMask
472 }
473 
474 void ScalarEnumerationTraits<WasmYAML::SymbolKind>::enumeration(
475     IO &IO, WasmYAML::SymbolKind &Kind) {
476 #define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_SYMBOL_TYPE_##X);
477   ECase(FUNCTION);
478   ECase(DATA);
479   ECase(GLOBAL);
480   ECase(SECTION);
481   ECase(EVENT);
482 #undef ECase
483 }
484 
485 void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
486     IO &IO, WasmYAML::ValueType &Type) {
487 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
488   ECase(I32);
489   ECase(I64);
490   ECase(F32);
491   ECase(F64);
492   ECase(V128);
493   ECase(ANYFUNC);
494   ECase(FUNC);
495   ECase(NORESULT);
496 #undef ECase
497 }
498 
499 void ScalarEnumerationTraits<WasmYAML::ExportKind>::enumeration(
500     IO &IO, WasmYAML::ExportKind &Kind) {
501 #define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_EXTERNAL_##X);
502   ECase(FUNCTION);
503   ECase(TABLE);
504   ECase(MEMORY);
505   ECase(GLOBAL);
506   ECase(EVENT);
507 #undef ECase
508 }
509 
510 void ScalarEnumerationTraits<WasmYAML::Opcode>::enumeration(
511     IO &IO, WasmYAML::Opcode &Code) {
512 #define ECase(X) IO.enumCase(Code, #X, wasm::WASM_OPCODE_##X);
513   ECase(END);
514   ECase(I32_CONST);
515   ECase(I64_CONST);
516   ECase(F64_CONST);
517   ECase(F32_CONST);
518   ECase(GET_GLOBAL);
519 #undef ECase
520 }
521 
522 void ScalarEnumerationTraits<WasmYAML::TableType>::enumeration(
523     IO &IO, WasmYAML::TableType &Type) {
524 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
525   ECase(ANYFUNC);
526 #undef ECase
527 }
528 
529 void ScalarEnumerationTraits<WasmYAML::RelocType>::enumeration(
530     IO &IO, WasmYAML::RelocType &Type) {
531 #define WASM_RELOC(name, value) IO.enumCase(Type, #name, wasm::name);
532 #include "llvm/BinaryFormat/WasmRelocs.def"
533 #undef WASM_RELOC
534 }
535 
536 } // end namespace yaml
537 
538 } // end namespace llvm
539