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