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