1 //===- yaml2wasm - Convert YAML to a Wasm object file --------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// 9 /// \file 10 /// The Wasm component of yaml2obj. 11 /// 12 //===----------------------------------------------------------------------===// 13 // 14 15 #include "llvm/Object/Wasm.h" 16 #include "llvm/ObjectYAML/ObjectYAML.h" 17 #include "llvm/ObjectYAML/yaml2obj.h" 18 #include "llvm/Support/Endian.h" 19 #include "llvm/Support/LEB128.h" 20 21 using namespace llvm; 22 23 namespace { 24 /// This parses a yaml stream that represents a Wasm object file. 25 /// See docs/yaml2obj for the yaml scheema. 26 class WasmWriter { 27 public: 28 WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {} 29 int writeWasm(raw_ostream &OS); 30 31 private: 32 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec, 33 uint32_t SectionIndex); 34 35 int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section); 36 int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section); 37 int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section); 38 int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section); 39 int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section); 40 int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section); 41 int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section); 42 int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section); 43 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section); 44 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section); 45 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section); 46 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section); 47 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section); 48 int writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section); 49 50 // Custom section types 51 int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section); 52 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section); 53 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section); 54 int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section); 55 int writeSectionContent(raw_ostream &OS, 56 WasmYAML::TargetFeaturesSection &Section); 57 WasmYAML::Object &Obj; 58 uint32_t NumImportedFunctions = 0; 59 uint32_t NumImportedGlobals = 0; 60 uint32_t NumImportedEvents = 0; 61 }; 62 63 class SubSectionWriter { 64 raw_ostream &OS; 65 std::string OutString; 66 raw_string_ostream StringStream; 67 68 public: 69 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {} 70 71 void done() { 72 StringStream.flush(); 73 encodeULEB128(OutString.size(), OS); 74 OS << OutString; 75 OutString.clear(); 76 } 77 78 raw_ostream &getStream() { return StringStream; } 79 }; 80 81 } // end anonymous namespace 82 83 static int writeUint64(raw_ostream &OS, uint64_t Value) { 84 char Data[sizeof(Value)]; 85 support::endian::write64le(Data, Value); 86 OS.write(Data, sizeof(Data)); 87 return 0; 88 } 89 90 static int writeUint32(raw_ostream &OS, uint32_t Value) { 91 char Data[sizeof(Value)]; 92 support::endian::write32le(Data, Value); 93 OS.write(Data, sizeof(Data)); 94 return 0; 95 } 96 97 static int writeUint8(raw_ostream &OS, uint8_t Value) { 98 char Data[sizeof(Value)]; 99 memcpy(Data, &Value, sizeof(Data)); 100 OS.write(Data, sizeof(Data)); 101 return 0; 102 } 103 104 static int writeStringRef(const StringRef &Str, raw_ostream &OS) { 105 encodeULEB128(Str.size(), OS); 106 OS << Str; 107 return 0; 108 } 109 110 static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) { 111 writeUint8(OS, Lim.Flags); 112 encodeULEB128(Lim.Initial, OS); 113 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) 114 encodeULEB128(Lim.Maximum, OS); 115 return 0; 116 } 117 118 static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) { 119 writeUint8(OS, InitExpr.Opcode); 120 switch (InitExpr.Opcode) { 121 case wasm::WASM_OPCODE_I32_CONST: 122 encodeSLEB128(InitExpr.Value.Int32, OS); 123 break; 124 case wasm::WASM_OPCODE_I64_CONST: 125 encodeSLEB128(InitExpr.Value.Int64, OS); 126 break; 127 case wasm::WASM_OPCODE_F32_CONST: 128 writeUint32(OS, InitExpr.Value.Float32); 129 break; 130 case wasm::WASM_OPCODE_F64_CONST: 131 writeUint64(OS, InitExpr.Value.Float64); 132 break; 133 case wasm::WASM_OPCODE_GLOBAL_GET: 134 encodeULEB128(InitExpr.Value.Global, OS); 135 break; 136 default: 137 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n"; 138 return 1; 139 } 140 writeUint8(OS, wasm::WASM_OPCODE_END); 141 return 0; 142 } 143 144 int WasmWriter::writeSectionContent(raw_ostream &OS, 145 WasmYAML::DylinkSection &Section) { 146 writeStringRef(Section.Name, OS); 147 encodeULEB128(Section.MemorySize, OS); 148 encodeULEB128(Section.MemoryAlignment, OS); 149 encodeULEB128(Section.TableSize, OS); 150 encodeULEB128(Section.TableAlignment, OS); 151 encodeULEB128(Section.Needed.size(), OS); 152 for (StringRef Needed : Section.Needed) { 153 writeStringRef(Needed, OS); 154 } 155 return 0; 156 } 157 158 int WasmWriter::writeSectionContent(raw_ostream &OS, 159 WasmYAML::LinkingSection &Section) { 160 writeStringRef(Section.Name, OS); 161 encodeULEB128(Section.Version, OS); 162 163 SubSectionWriter SubSection(OS); 164 165 // SYMBOL_TABLE subsection 166 if (Section.SymbolTable.size()) { 167 writeUint8(OS, wasm::WASM_SYMBOL_TABLE); 168 169 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream()); 170 #ifndef NDEBUG 171 uint32_t SymbolIndex = 0; 172 #endif 173 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) { 174 assert(Info.Index == SymbolIndex++); 175 writeUint8(SubSection.getStream(), Info.Kind); 176 encodeULEB128(Info.Flags, SubSection.getStream()); 177 switch (Info.Kind) { 178 case wasm::WASM_SYMBOL_TYPE_FUNCTION: 179 case wasm::WASM_SYMBOL_TYPE_GLOBAL: 180 case wasm::WASM_SYMBOL_TYPE_EVENT: 181 encodeULEB128(Info.ElementIndex, SubSection.getStream()); 182 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || 183 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) 184 writeStringRef(Info.Name, SubSection.getStream()); 185 break; 186 case wasm::WASM_SYMBOL_TYPE_DATA: 187 writeStringRef(Info.Name, SubSection.getStream()); 188 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) { 189 encodeULEB128(Info.DataRef.Segment, SubSection.getStream()); 190 encodeULEB128(Info.DataRef.Offset, SubSection.getStream()); 191 encodeULEB128(Info.DataRef.Size, SubSection.getStream()); 192 } 193 break; 194 case wasm::WASM_SYMBOL_TYPE_SECTION: 195 encodeULEB128(Info.ElementIndex, SubSection.getStream()); 196 break; 197 default: 198 llvm_unreachable("unexpected kind"); 199 } 200 } 201 202 SubSection.done(); 203 } 204 205 // SEGMENT_NAMES subsection 206 if (Section.SegmentInfos.size()) { 207 writeUint8(OS, wasm::WASM_SEGMENT_INFO); 208 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream()); 209 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) { 210 writeStringRef(SegmentInfo.Name, SubSection.getStream()); 211 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream()); 212 encodeULEB128(SegmentInfo.Flags, SubSection.getStream()); 213 } 214 SubSection.done(); 215 } 216 217 // INIT_FUNCS subsection 218 if (Section.InitFunctions.size()) { 219 writeUint8(OS, wasm::WASM_INIT_FUNCS); 220 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream()); 221 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) { 222 encodeULEB128(Func.Priority, SubSection.getStream()); 223 encodeULEB128(Func.Symbol, SubSection.getStream()); 224 } 225 SubSection.done(); 226 } 227 228 // COMDAT_INFO subsection 229 if (Section.Comdats.size()) { 230 writeUint8(OS, wasm::WASM_COMDAT_INFO); 231 encodeULEB128(Section.Comdats.size(), SubSection.getStream()); 232 for (const auto &C : Section.Comdats) { 233 writeStringRef(C.Name, SubSection.getStream()); 234 encodeULEB128(0, SubSection.getStream()); // flags for future use 235 encodeULEB128(C.Entries.size(), SubSection.getStream()); 236 for (const WasmYAML::ComdatEntry &Entry : C.Entries) { 237 writeUint8(SubSection.getStream(), Entry.Kind); 238 encodeULEB128(Entry.Index, SubSection.getStream()); 239 } 240 } 241 SubSection.done(); 242 } 243 244 return 0; 245 } 246 247 int WasmWriter::writeSectionContent(raw_ostream &OS, 248 WasmYAML::NameSection &Section) { 249 writeStringRef(Section.Name, OS); 250 if (Section.FunctionNames.size()) { 251 writeUint8(OS, wasm::WASM_NAMES_FUNCTION); 252 253 SubSectionWriter SubSection(OS); 254 255 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream()); 256 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) { 257 encodeULEB128(NameEntry.Index, SubSection.getStream()); 258 writeStringRef(NameEntry.Name, SubSection.getStream()); 259 } 260 261 SubSection.done(); 262 } 263 return 0; 264 } 265 266 int WasmWriter::writeSectionContent(raw_ostream &OS, 267 WasmYAML::ProducersSection &Section) { 268 writeStringRef(Section.Name, OS); 269 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) + 270 int(!Section.SDKs.empty()); 271 if (Fields == 0) 272 return 0; 273 encodeULEB128(Fields, OS); 274 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages), 275 std::make_pair(StringRef("processed-by"), &Section.Tools), 276 std::make_pair(StringRef("sdk"), &Section.SDKs)}) { 277 if (Field.second->empty()) 278 continue; 279 writeStringRef(Field.first, OS); 280 encodeULEB128(Field.second->size(), OS); 281 for (auto &Entry : *Field.second) { 282 writeStringRef(Entry.Name, OS); 283 writeStringRef(Entry.Version, OS); 284 } 285 } 286 return 0; 287 } 288 289 int WasmWriter::writeSectionContent(raw_ostream &OS, 290 WasmYAML::TargetFeaturesSection &Section) { 291 writeStringRef(Section.Name, OS); 292 encodeULEB128(Section.Features.size(), OS); 293 for (auto &E : Section.Features) { 294 writeUint8(OS, E.Prefix); 295 writeStringRef(E.Name, OS); 296 } 297 return 0; 298 } 299 300 int WasmWriter::writeSectionContent(raw_ostream &OS, 301 WasmYAML::CustomSection &Section) { 302 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) { 303 if (auto Err = writeSectionContent(OS, *S)) 304 return Err; 305 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) { 306 if (auto Err = writeSectionContent(OS, *S)) 307 return Err; 308 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) { 309 if (auto Err = writeSectionContent(OS, *S)) 310 return Err; 311 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) { 312 if (auto Err = writeSectionContent(OS, *S)) 313 return Err; 314 } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) { 315 if (auto Err = writeSectionContent(OS, *S)) 316 return Err; 317 } else { 318 writeStringRef(Section.Name, OS); 319 Section.Payload.writeAsBinary(OS); 320 } 321 return 0; 322 } 323 324 int WasmWriter::writeSectionContent(raw_ostream &OS, 325 WasmYAML::TypeSection &Section) { 326 encodeULEB128(Section.Signatures.size(), OS); 327 uint32_t ExpectedIndex = 0; 328 for (const WasmYAML::Signature &Sig : Section.Signatures) { 329 if (Sig.Index != ExpectedIndex) { 330 errs() << "Unexpected type index: " << Sig.Index << "\n"; 331 return 1; 332 } 333 ++ExpectedIndex; 334 writeUint8(OS, Sig.Form); 335 encodeULEB128(Sig.ParamTypes.size(), OS); 336 for (auto ParamType : Sig.ParamTypes) 337 writeUint8(OS, ParamType); 338 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) { 339 encodeULEB128(0, OS); 340 } else { 341 encodeULEB128(1, OS); 342 writeUint8(OS, Sig.ReturnType); 343 } 344 } 345 return 0; 346 } 347 348 int WasmWriter::writeSectionContent(raw_ostream &OS, 349 WasmYAML::ImportSection &Section) { 350 encodeULEB128(Section.Imports.size(), OS); 351 for (const WasmYAML::Import &Import : Section.Imports) { 352 writeStringRef(Import.Module, OS); 353 writeStringRef(Import.Field, OS); 354 writeUint8(OS, Import.Kind); 355 switch (Import.Kind) { 356 case wasm::WASM_EXTERNAL_FUNCTION: 357 encodeULEB128(Import.SigIndex, OS); 358 NumImportedFunctions++; 359 break; 360 case wasm::WASM_EXTERNAL_GLOBAL: 361 writeUint8(OS, Import.GlobalImport.Type); 362 writeUint8(OS, Import.GlobalImport.Mutable); 363 NumImportedGlobals++; 364 break; 365 case wasm::WASM_EXTERNAL_EVENT: 366 writeUint32(OS, Import.EventImport.Attribute); 367 writeUint32(OS, Import.EventImport.SigIndex); 368 NumImportedGlobals++; 369 break; 370 case wasm::WASM_EXTERNAL_MEMORY: 371 writeLimits(Import.Memory, OS); 372 break; 373 case wasm::WASM_EXTERNAL_TABLE: 374 writeUint8(OS, Import.TableImport.ElemType); 375 writeLimits(Import.TableImport.TableLimits, OS); 376 break; 377 default: 378 errs() << "Unknown import type: " << Import.Kind << "\n"; 379 return 1; 380 } 381 } 382 return 0; 383 } 384 385 int WasmWriter::writeSectionContent(raw_ostream &OS, 386 WasmYAML::FunctionSection &Section) { 387 encodeULEB128(Section.FunctionTypes.size(), OS); 388 for (uint32_t FuncType : Section.FunctionTypes) { 389 encodeULEB128(FuncType, OS); 390 } 391 return 0; 392 } 393 394 int WasmWriter::writeSectionContent(raw_ostream &OS, 395 WasmYAML::ExportSection &Section) { 396 encodeULEB128(Section.Exports.size(), OS); 397 for (const WasmYAML::Export &Export : Section.Exports) { 398 writeStringRef(Export.Name, OS); 399 writeUint8(OS, Export.Kind); 400 encodeULEB128(Export.Index, OS); 401 } 402 return 0; 403 } 404 405 int WasmWriter::writeSectionContent(raw_ostream &OS, 406 WasmYAML::StartSection &Section) { 407 encodeULEB128(Section.StartFunction, OS); 408 return 0; 409 } 410 411 int WasmWriter::writeSectionContent(raw_ostream &OS, 412 WasmYAML::TableSection &Section) { 413 encodeULEB128(Section.Tables.size(), OS); 414 for (auto &Table : Section.Tables) { 415 writeUint8(OS, Table.ElemType); 416 writeLimits(Table.TableLimits, OS); 417 } 418 return 0; 419 } 420 421 int WasmWriter::writeSectionContent(raw_ostream &OS, 422 WasmYAML::MemorySection &Section) { 423 encodeULEB128(Section.Memories.size(), OS); 424 for (const WasmYAML::Limits &Mem : Section.Memories) { 425 writeLimits(Mem, OS); 426 } 427 return 0; 428 } 429 430 int WasmWriter::writeSectionContent(raw_ostream &OS, 431 WasmYAML::GlobalSection &Section) { 432 encodeULEB128(Section.Globals.size(), OS); 433 uint32_t ExpectedIndex = NumImportedGlobals; 434 for (auto &Global : Section.Globals) { 435 if (Global.Index != ExpectedIndex) { 436 errs() << "Unexpected global index: " << Global.Index << "\n"; 437 return 1; 438 } 439 ++ExpectedIndex; 440 writeUint8(OS, Global.Type); 441 writeUint8(OS, Global.Mutable); 442 writeInitExpr(Global.InitExpr, OS); 443 } 444 return 0; 445 } 446 447 int WasmWriter::writeSectionContent(raw_ostream &OS, 448 WasmYAML::EventSection &Section) { 449 encodeULEB128(Section.Events.size(), OS); 450 uint32_t ExpectedIndex = NumImportedEvents; 451 for (auto &Event : Section.Events) { 452 if (Event.Index != ExpectedIndex) { 453 errs() << "Unexpected event index: " << Event.Index << "\n"; 454 return 1; 455 } 456 ++ExpectedIndex; 457 encodeULEB128(Event.Attribute, OS); 458 encodeULEB128(Event.SigIndex, OS); 459 } 460 return 0; 461 } 462 463 int WasmWriter::writeSectionContent(raw_ostream &OS, 464 WasmYAML::ElemSection &Section) { 465 encodeULEB128(Section.Segments.size(), OS); 466 for (auto &Segment : Section.Segments) { 467 encodeULEB128(Segment.TableIndex, OS); 468 writeInitExpr(Segment.Offset, OS); 469 470 encodeULEB128(Segment.Functions.size(), OS); 471 for (auto &Function : Segment.Functions) { 472 encodeULEB128(Function, OS); 473 } 474 } 475 return 0; 476 } 477 478 int WasmWriter::writeSectionContent(raw_ostream &OS, 479 WasmYAML::CodeSection &Section) { 480 encodeULEB128(Section.Functions.size(), OS); 481 uint32_t ExpectedIndex = NumImportedFunctions; 482 for (auto &Func : Section.Functions) { 483 std::string OutString; 484 raw_string_ostream StringStream(OutString); 485 if (Func.Index != ExpectedIndex) { 486 errs() << "Unexpected function index: " << Func.Index << "\n"; 487 return 1; 488 } 489 ++ExpectedIndex; 490 491 encodeULEB128(Func.Locals.size(), StringStream); 492 for (auto &LocalDecl : Func.Locals) { 493 encodeULEB128(LocalDecl.Count, StringStream); 494 writeUint8(StringStream, LocalDecl.Type); 495 } 496 497 Func.Body.writeAsBinary(StringStream); 498 499 // Write the section size followed by the content 500 StringStream.flush(); 501 encodeULEB128(OutString.size(), OS); 502 OS << OutString; 503 } 504 return 0; 505 } 506 507 int WasmWriter::writeSectionContent(raw_ostream &OS, 508 WasmYAML::DataSection &Section) { 509 encodeULEB128(Section.Segments.size(), OS); 510 for (auto &Segment : Section.Segments) { 511 encodeULEB128(Segment.InitFlags, OS); 512 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX) 513 encodeULEB128(Segment.MemoryIndex, OS); 514 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) 515 writeInitExpr(Segment.Offset, OS); 516 encodeULEB128(Segment.Content.binary_size(), OS); 517 Segment.Content.writeAsBinary(OS); 518 } 519 return 0; 520 } 521 522 int WasmWriter::writeSectionContent(raw_ostream &OS, 523 WasmYAML::DataCountSection &Section) { 524 encodeULEB128(Section.Count, OS); 525 return 0; 526 } 527 528 int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec, 529 uint32_t SectionIndex) { 530 switch (Sec.Type) { 531 case wasm::WASM_SEC_CODE: 532 writeStringRef("reloc.CODE", OS); 533 break; 534 case wasm::WASM_SEC_DATA: 535 writeStringRef("reloc.DATA", OS); 536 break; 537 case wasm::WASM_SEC_CUSTOM: { 538 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec); 539 writeStringRef(("reloc." + CustomSection->Name).str(), OS); 540 break; 541 } 542 default: 543 llvm_unreachable("not yet implemented"); 544 return 1; 545 } 546 547 encodeULEB128(SectionIndex, OS); 548 encodeULEB128(Sec.Relocations.size(), OS); 549 550 for (auto Reloc : Sec.Relocations) { 551 writeUint8(OS, Reloc.Type); 552 encodeULEB128(Reloc.Offset, OS); 553 encodeULEB128(Reloc.Index, OS); 554 switch (Reloc.Type) { 555 case wasm::R_WASM_MEMORY_ADDR_LEB: 556 case wasm::R_WASM_MEMORY_ADDR_SLEB: 557 case wasm::R_WASM_MEMORY_ADDR_I32: 558 case wasm::R_WASM_FUNCTION_OFFSET_I32: 559 case wasm::R_WASM_SECTION_OFFSET_I32: 560 encodeULEB128(Reloc.Addend, OS); 561 } 562 } 563 return 0; 564 } 565 566 int WasmWriter::writeWasm(raw_ostream &OS) { 567 // Write headers 568 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic)); 569 writeUint32(OS, Obj.Header.Version); 570 571 // Write each section 572 llvm::object::WasmSectionOrderChecker Checker; 573 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) { 574 StringRef SecName = ""; 575 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) 576 SecName = S->Name; 577 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) { 578 errs() << "Out of order section type: " << Sec->Type << "\n"; 579 return 1; 580 } 581 encodeULEB128(Sec->Type, OS); 582 std::string OutString; 583 raw_string_ostream StringStream(OutString); 584 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) { 585 if (auto Err = writeSectionContent(StringStream, *S)) 586 return Err; 587 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) { 588 if (auto Err = writeSectionContent(StringStream, *S)) 589 return Err; 590 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) { 591 if (auto Err = writeSectionContent(StringStream, *S)) 592 return Err; 593 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) { 594 if (auto Err = writeSectionContent(StringStream, *S)) 595 return Err; 596 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) { 597 if (auto Err = writeSectionContent(StringStream, *S)) 598 return Err; 599 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) { 600 if (auto Err = writeSectionContent(StringStream, *S)) 601 return Err; 602 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) { 603 if (auto Err = writeSectionContent(StringStream, *S)) 604 return Err; 605 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) { 606 if (auto Err = writeSectionContent(StringStream, *S)) 607 return Err; 608 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) { 609 if (auto Err = writeSectionContent(StringStream, *S)) 610 return Err; 611 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) { 612 if (auto Err = writeSectionContent(StringStream, *S)) 613 return Err; 614 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) { 615 if (auto Err = writeSectionContent(StringStream, *S)) 616 return Err; 617 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) { 618 if (auto Err = writeSectionContent(StringStream, *S)) 619 return Err; 620 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) { 621 if (auto Err = writeSectionContent(StringStream, *S)) 622 return Err; 623 } else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get())) { 624 if (auto Err = writeSectionContent(StringStream, *S)) 625 return Err; 626 } else { 627 errs() << "Unknown section type: " << Sec->Type << "\n"; 628 return 1; 629 } 630 StringStream.flush(); 631 632 // Write the section size followed by the content 633 encodeULEB128(OutString.size(), OS); 634 OS << OutString; 635 } 636 637 // write reloc sections for any section that have relocations 638 uint32_t SectionIndex = 0; 639 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) { 640 if (Sec->Relocations.empty()) { 641 SectionIndex++; 642 continue; 643 } 644 645 writeUint8(OS, wasm::WASM_SEC_CUSTOM); 646 std::string OutString; 647 raw_string_ostream StringStream(OutString); 648 writeRelocSection(StringStream, *Sec, SectionIndex++); 649 StringStream.flush(); 650 651 encodeULEB128(OutString.size(), OS); 652 OS << OutString; 653 } 654 655 return 0; 656 } 657 658 namespace llvm { 659 namespace yaml { 660 661 int yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out) { 662 WasmWriter Writer(Doc); 663 664 return Writer.writeWasm(Out); 665 } 666 667 } // namespace yaml 668 } // namespace llvm 669