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