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/Object/Wasm.h"
16 #include "llvm/Support/Casting.h"
17 #include "llvm/Support/MipsABIFlags.h"
18 
19 namespace llvm {
20 
21 namespace WasmYAML {
22 
23 // Declared here rather than in the header to comply with:
24 // http://llvm.org/docs/CodingStandards.html#provide-a-virtual-method-anchor-for-classes-in-headers
25 Section::~Section() {}
26 
27 } // end namespace WasmYAML
28 
29 namespace yaml {
30 
31 void MappingTraits<WasmYAML::FileHeader>::mapping(
32     IO &IO, WasmYAML::FileHeader &FileHdr) {
33   IO.mapRequired("Version", FileHdr.Version);
34 }
35 
36 void MappingTraits<WasmYAML::Object>::mapping(IO &IO,
37                                               WasmYAML::Object &Object) {
38   IO.setContext(&Object);
39   IO.mapTag("!WASM", true);
40   IO.mapRequired("FileHeader", Object.Header);
41   IO.mapOptional("Sections", Object.Sections);
42   IO.setContext(nullptr);
43 }
44 
45 static void commonSectionMapping(IO &IO, WasmYAML::Section &Section) {
46   IO.mapRequired("Type", Section.Type);
47   IO.mapOptional("Relocations", Section.Relocations);
48 }
49 
50 static void sectionMapping(IO &IO, WasmYAML::NameSection &Section) {
51   commonSectionMapping(IO, Section);
52   IO.mapRequired("Name", Section.Name);
53   IO.mapOptional("FunctionNames", Section.FunctionNames);
54 }
55 
56 static void sectionMapping(IO &IO, WasmYAML::LinkingSection &Section) {
57   commonSectionMapping(IO, Section);
58   IO.mapRequired("Name", Section.Name);
59   IO.mapRequired("SymbolInfo", Section.SymbolInfos);
60 }
61 
62 static void sectionMapping(IO &IO, WasmYAML::CustomSection &Section) {
63   commonSectionMapping(IO, Section);
64   IO.mapRequired("Name", Section.Name);
65   IO.mapRequired("Payload", Section.Payload);
66 }
67 
68 static void sectionMapping(IO &IO, WasmYAML::TypeSection &Section) {
69   commonSectionMapping(IO, Section);
70   IO.mapOptional("Signatures", Section.Signatures);
71 }
72 
73 static void sectionMapping(IO &IO, WasmYAML::ImportSection &Section) {
74   commonSectionMapping(IO, Section);
75   IO.mapOptional("Imports", Section.Imports);
76 }
77 
78 static void sectionMapping(IO &IO, WasmYAML::FunctionSection &Section) {
79   commonSectionMapping(IO, Section);
80   IO.mapOptional("FunctionTypes", Section.FunctionTypes);
81 }
82 
83 static void sectionMapping(IO &IO, WasmYAML::TableSection &Section) {
84   commonSectionMapping(IO, Section);
85   IO.mapOptional("Tables", Section.Tables);
86 }
87 
88 static void sectionMapping(IO &IO, WasmYAML::MemorySection &Section) {
89   commonSectionMapping(IO, Section);
90   IO.mapOptional("Memories", Section.Memories);
91 }
92 
93 static void sectionMapping(IO &IO, WasmYAML::GlobalSection &Section) {
94   commonSectionMapping(IO, Section);
95   IO.mapOptional("Globals", Section.Globals);
96 }
97 
98 static void sectionMapping(IO &IO, WasmYAML::ExportSection &Section) {
99   commonSectionMapping(IO, Section);
100   IO.mapOptional("Exports", Section.Exports);
101 }
102 
103 static void sectionMapping(IO &IO, WasmYAML::StartSection &Section) {
104   commonSectionMapping(IO, Section);
105   IO.mapOptional("StartFunction", Section.StartFunction);
106 }
107 
108 static void sectionMapping(IO &IO, WasmYAML::ElemSection &Section) {
109   commonSectionMapping(IO, Section);
110   IO.mapOptional("Segments", Section.Segments);
111 }
112 
113 static void sectionMapping(IO &IO, WasmYAML::CodeSection &Section) {
114   commonSectionMapping(IO, Section);
115   IO.mapRequired("Functions", Section.Functions);
116 }
117 
118 static void sectionMapping(IO &IO, WasmYAML::DataSection &Section) {
119   commonSectionMapping(IO, Section);
120   IO.mapRequired("Segments", Section.Segments);
121 }
122 
123 void MappingTraits<std::unique_ptr<WasmYAML::Section>>::mapping(
124     IO &IO, std::unique_ptr<WasmYAML::Section> &Section) {
125   WasmYAML::SectionType SectionType;
126   if (IO.outputting())
127     SectionType = Section->Type;
128   else
129     IO.mapRequired("Type", SectionType);
130 
131   switch (SectionType) {
132   case wasm::WASM_SEC_CUSTOM: {
133     StringRef SectionName;
134     if (IO.outputting()) {
135       auto CustomSection = cast<WasmYAML::CustomSection>(Section.get());
136       SectionName = CustomSection->Name;
137     } else {
138       IO.mapRequired("Name", SectionName);
139     }
140     if (SectionName == "linking") {
141       if (!IO.outputting())
142         Section.reset(new WasmYAML::LinkingSection());
143       sectionMapping(IO, *cast<WasmYAML::LinkingSection>(Section.get()));
144     } else if (SectionName == "name") {
145       if (!IO.outputting())
146         Section.reset(new WasmYAML::NameSection());
147       sectionMapping(IO, *cast<WasmYAML::NameSection>(Section.get()));
148     } else {
149       if (!IO.outputting())
150         Section.reset(new WasmYAML::CustomSection(SectionName));
151       sectionMapping(IO, *cast<WasmYAML::CustomSection>(Section.get()));
152     }
153     break;
154   }
155   case wasm::WASM_SEC_TYPE:
156     if (!IO.outputting())
157       Section.reset(new WasmYAML::TypeSection());
158     sectionMapping(IO, *cast<WasmYAML::TypeSection>(Section.get()));
159     break;
160   case wasm::WASM_SEC_IMPORT:
161     if (!IO.outputting())
162       Section.reset(new WasmYAML::ImportSection());
163     sectionMapping(IO, *cast<WasmYAML::ImportSection>(Section.get()));
164     break;
165   case wasm::WASM_SEC_FUNCTION:
166     if (!IO.outputting())
167       Section.reset(new WasmYAML::FunctionSection());
168     sectionMapping(IO, *cast<WasmYAML::FunctionSection>(Section.get()));
169     break;
170   case wasm::WASM_SEC_TABLE:
171     if (!IO.outputting())
172       Section.reset(new WasmYAML::TableSection());
173     sectionMapping(IO, *cast<WasmYAML::TableSection>(Section.get()));
174     break;
175   case wasm::WASM_SEC_MEMORY:
176     if (!IO.outputting())
177       Section.reset(new WasmYAML::MemorySection());
178     sectionMapping(IO, *cast<WasmYAML::MemorySection>(Section.get()));
179     break;
180   case wasm::WASM_SEC_GLOBAL:
181     if (!IO.outputting())
182       Section.reset(new WasmYAML::GlobalSection());
183     sectionMapping(IO, *cast<WasmYAML::GlobalSection>(Section.get()));
184     break;
185   case wasm::WASM_SEC_EXPORT:
186     if (!IO.outputting())
187       Section.reset(new WasmYAML::ExportSection());
188     sectionMapping(IO, *cast<WasmYAML::ExportSection>(Section.get()));
189     break;
190   case wasm::WASM_SEC_START:
191     if (!IO.outputting())
192       Section.reset(new WasmYAML::StartSection());
193     sectionMapping(IO, *cast<WasmYAML::StartSection>(Section.get()));
194     break;
195   case wasm::WASM_SEC_ELEM:
196     if (!IO.outputting())
197       Section.reset(new WasmYAML::ElemSection());
198     sectionMapping(IO, *cast<WasmYAML::ElemSection>(Section.get()));
199     break;
200   case wasm::WASM_SEC_CODE:
201     if (!IO.outputting())
202       Section.reset(new WasmYAML::CodeSection());
203     sectionMapping(IO, *cast<WasmYAML::CodeSection>(Section.get()));
204     break;
205   case wasm::WASM_SEC_DATA:
206     if (!IO.outputting())
207       Section.reset(new WasmYAML::DataSection());
208     sectionMapping(IO, *cast<WasmYAML::DataSection>(Section.get()));
209     break;
210   default:
211     llvm_unreachable("Unknown section type");
212   }
213 }
214 
215 void ScalarEnumerationTraits<WasmYAML::SectionType>::enumeration(
216     IO &IO, WasmYAML::SectionType &Type) {
217 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_SEC_##X);
218   ECase(CUSTOM);
219   ECase(TYPE);
220   ECase(IMPORT);
221   ECase(FUNCTION);
222   ECase(TABLE);
223   ECase(MEMORY);
224   ECase(GLOBAL);
225   ECase(EXPORT);
226   ECase(START);
227   ECase(ELEM);
228   ECase(CODE);
229   ECase(DATA);
230 #undef ECase
231 }
232 
233 void MappingTraits<WasmYAML::Signature>::mapping(
234     IO &IO, WasmYAML::Signature &Signature) {
235   IO.mapOptional("Index", Signature.Index);
236   IO.mapRequired("ReturnType", Signature.ReturnType);
237   IO.mapRequired("ParamTypes", Signature.ParamTypes);
238 }
239 
240 void MappingTraits<WasmYAML::Table>::mapping(IO &IO, WasmYAML::Table &Table) {
241   IO.mapRequired("ElemType", Table.ElemType);
242   IO.mapRequired("Limits", Table.TableLimits);
243 }
244 
245 void MappingTraits<WasmYAML::Function>::mapping(IO &IO,
246                                                 WasmYAML::Function &Function) {
247   IO.mapRequired("Locals", Function.Locals);
248   IO.mapRequired("Body", Function.Body);
249 }
250 
251 void MappingTraits<WasmYAML::Relocation>::mapping(
252     IO &IO, WasmYAML::Relocation &Relocation) {
253   IO.mapRequired("Type", Relocation.Type);
254   IO.mapRequired("Index", Relocation.Index);
255   IO.mapRequired("Offset", Relocation.Offset);
256   IO.mapOptional("Addend", Relocation.Addend, 0);
257 }
258 
259 void MappingTraits<WasmYAML::NameEntry>::mapping(
260     IO &IO, WasmYAML::NameEntry &NameEntry) {
261   IO.mapRequired("Index", NameEntry.Index);
262   IO.mapRequired("Name", NameEntry.Name);
263 }
264 
265 void MappingTraits<WasmYAML::LocalDecl>::mapping(
266     IO &IO, WasmYAML::LocalDecl &LocalDecl) {
267   IO.mapRequired("Type", LocalDecl.Type);
268   IO.mapRequired("Count", LocalDecl.Count);
269 }
270 
271 void MappingTraits<WasmYAML::Limits>::mapping(IO &IO,
272                                               WasmYAML::Limits &Limits) {
273   if (!IO.outputting() || Limits.Flags)
274     IO.mapOptional("Flags", Limits.Flags);
275   IO.mapRequired("Initial", Limits.Initial);
276   if (!IO.outputting() || Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
277     IO.mapOptional("Maximum", Limits.Maximum);
278 }
279 
280 void MappingTraits<WasmYAML::ElemSegment>::mapping(
281     IO &IO, WasmYAML::ElemSegment &Segment) {
282   IO.mapRequired("Offset", Segment.Offset);
283   IO.mapRequired("Functions", Segment.Functions);
284 }
285 
286 void MappingTraits<WasmYAML::Import>::mapping(IO &IO,
287                                               WasmYAML::Import &Import) {
288   IO.mapRequired("Module", Import.Module);
289   IO.mapRequired("Field", Import.Field);
290   IO.mapRequired("Kind", Import.Kind);
291   if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
292     IO.mapRequired("SigIndex", Import.SigIndex);
293   } else if (Import.Kind == wasm::WASM_EXTERNAL_GLOBAL) {
294     IO.mapRequired("GlobalType", Import.GlobalImport.Type);
295     IO.mapRequired("GlobalMutable", Import.GlobalImport.Mutable);
296   } else if (Import.Kind == wasm::WASM_EXTERNAL_TABLE) {
297     IO.mapRequired("Table", Import.TableImport);
298   } else if (Import.Kind == wasm::WASM_EXTERNAL_MEMORY ) {
299     IO.mapRequired("Memory", Import.Memory);
300   } else {
301     llvm_unreachable("unhandled import type");
302   }
303 }
304 
305 void MappingTraits<WasmYAML::Export>::mapping(IO &IO,
306                                               WasmYAML::Export &Export) {
307   IO.mapRequired("Name", Export.Name);
308   IO.mapRequired("Kind", Export.Kind);
309   IO.mapRequired("Index", Export.Index);
310 }
311 
312 void MappingTraits<WasmYAML::Global>::mapping(IO &IO,
313                                               WasmYAML::Global &Global) {
314   IO.mapRequired("Type", Global.Type);
315   IO.mapRequired("Mutable", Global.Mutable);
316   IO.mapRequired("InitExpr", Global.InitExpr);
317 }
318 
319 void MappingTraits<wasm::WasmInitExpr>::mapping(IO &IO,
320                                                 wasm::WasmInitExpr &Expr) {
321   WasmYAML::Opcode Op = Expr.Opcode;
322   IO.mapRequired("Opcode", Op);
323   Expr.Opcode = Op;
324   switch (Expr.Opcode) {
325   case wasm::WASM_OPCODE_I32_CONST:
326     IO.mapRequired("Value", Expr.Value.Int32);
327     break;
328   case wasm::WASM_OPCODE_I64_CONST:
329     IO.mapRequired("Value", Expr.Value.Int64);
330     break;
331   case wasm::WASM_OPCODE_F32_CONST:
332     IO.mapRequired("Value", Expr.Value.Float32);
333     break;
334   case wasm::WASM_OPCODE_F64_CONST:
335     IO.mapRequired("Value", Expr.Value.Float64);
336     break;
337   case wasm::WASM_OPCODE_GET_GLOBAL:
338     IO.mapRequired("Index", Expr.Value.Global);
339     break;
340   }
341 }
342 
343 void MappingTraits<WasmYAML::DataSegment>::mapping(
344     IO &IO, WasmYAML::DataSegment &Segment) {
345   IO.mapRequired("Index", Segment.Index);
346   IO.mapRequired("Offset", Segment.Offset);
347   IO.mapRequired("Content", Segment.Content);
348 }
349 
350 void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
351                                                   WasmYAML::SymbolInfo &Info) {
352   IO.mapRequired("Name", Info.Name);
353   IO.mapRequired("Flags", Info.Flags);
354 }
355 
356 void ScalarEnumerationTraits<WasmYAML::ValueType>::enumeration(
357     IO &IO, WasmYAML::ValueType &Type) {
358 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
359   ECase(I32);
360   ECase(I64);
361   ECase(F32);
362   ECase(F64);
363   ECase(ANYFUNC);
364   ECase(FUNC);
365   ECase(NORESULT);
366 #undef ECase
367 }
368 
369 void ScalarEnumerationTraits<WasmYAML::ExportKind>::enumeration(
370     IO &IO, WasmYAML::ExportKind &Kind) {
371 #define ECase(X) IO.enumCase(Kind, #X, wasm::WASM_EXTERNAL_##X);
372   ECase(FUNCTION);
373   ECase(TABLE);
374   ECase(MEMORY);
375   ECase(GLOBAL);
376 #undef ECase
377 }
378 
379 void ScalarEnumerationTraits<WasmYAML::Opcode>::enumeration(
380     IO &IO, WasmYAML::Opcode &Code) {
381 #define ECase(X) IO.enumCase(Code, #X, wasm::WASM_OPCODE_##X);
382   ECase(END);
383   ECase(I32_CONST);
384   ECase(I64_CONST);
385   ECase(F64_CONST);
386   ECase(F32_CONST);
387   ECase(GET_GLOBAL);
388 #undef ECase
389 }
390 
391 void ScalarEnumerationTraits<WasmYAML::TableType>::enumeration(
392     IO &IO, WasmYAML::TableType &Type) {
393 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
394   ECase(ANYFUNC);
395 #undef ECase
396 }
397 
398 void ScalarEnumerationTraits<WasmYAML::RelocType>::enumeration(
399     IO &IO, WasmYAML::RelocType &Type) {
400 #define WASM_RELOC(name, value) IO.enumCase(Type, #name, wasm::name);
401 #include "llvm/BinaryFormat/WasmRelocs/WebAssembly.def"
402 #undef WASM_RELOC
403 }
404 
405 } // end namespace yaml
406 } // end namespace llvm
407