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