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::EventSection &Section); 45 void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &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 encodeULEB128(Sig.ReturnTypes.size(), OS); 338 for (auto ReturnType : Sig.ReturnTypes) 339 writeUint8(OS, ReturnType); 340 } 341 } 342 343 void WasmWriter::writeSectionContent(raw_ostream &OS, 344 WasmYAML::ImportSection &Section) { 345 encodeULEB128(Section.Imports.size(), OS); 346 for (const WasmYAML::Import &Import : Section.Imports) { 347 writeStringRef(Import.Module, OS); 348 writeStringRef(Import.Field, OS); 349 writeUint8(OS, Import.Kind); 350 switch (Import.Kind) { 351 case wasm::WASM_EXTERNAL_FUNCTION: 352 encodeULEB128(Import.SigIndex, OS); 353 NumImportedFunctions++; 354 break; 355 case wasm::WASM_EXTERNAL_GLOBAL: 356 writeUint8(OS, Import.GlobalImport.Type); 357 writeUint8(OS, Import.GlobalImport.Mutable); 358 NumImportedGlobals++; 359 break; 360 case wasm::WASM_EXTERNAL_EVENT: 361 writeUint32(OS, Import.EventImport.Attribute); 362 writeUint32(OS, Import.EventImport.SigIndex); 363 NumImportedGlobals++; 364 break; 365 case wasm::WASM_EXTERNAL_MEMORY: 366 writeLimits(Import.Memory, OS); 367 break; 368 case wasm::WASM_EXTERNAL_TABLE: 369 writeUint8(OS, Import.TableImport.ElemType); 370 writeLimits(Import.TableImport.TableLimits, OS); 371 break; 372 default: 373 reportError("unknown import type: " +Twine(Import.Kind)); 374 return; 375 } 376 } 377 } 378 379 void WasmWriter::writeSectionContent(raw_ostream &OS, 380 WasmYAML::FunctionSection &Section) { 381 encodeULEB128(Section.FunctionTypes.size(), OS); 382 for (uint32_t FuncType : Section.FunctionTypes) 383 encodeULEB128(FuncType, OS); 384 } 385 386 void WasmWriter::writeSectionContent(raw_ostream &OS, 387 WasmYAML::ExportSection &Section) { 388 encodeULEB128(Section.Exports.size(), OS); 389 for (const WasmYAML::Export &Export : Section.Exports) { 390 writeStringRef(Export.Name, OS); 391 writeUint8(OS, Export.Kind); 392 encodeULEB128(Export.Index, OS); 393 } 394 } 395 396 void WasmWriter::writeSectionContent(raw_ostream &OS, 397 WasmYAML::StartSection &Section) { 398 encodeULEB128(Section.StartFunction, OS); 399 } 400 401 void WasmWriter::writeSectionContent(raw_ostream &OS, 402 WasmYAML::TableSection &Section) { 403 encodeULEB128(Section.Tables.size(), OS); 404 for (auto &Table : Section.Tables) { 405 writeUint8(OS, Table.ElemType); 406 writeLimits(Table.TableLimits, OS); 407 } 408 } 409 410 void WasmWriter::writeSectionContent(raw_ostream &OS, 411 WasmYAML::MemorySection &Section) { 412 encodeULEB128(Section.Memories.size(), OS); 413 for (const WasmYAML::Limits &Mem : Section.Memories) 414 writeLimits(Mem, OS); 415 } 416 417 void WasmWriter::writeSectionContent(raw_ostream &OS, 418 WasmYAML::EventSection &Section) { 419 encodeULEB128(Section.Events.size(), OS); 420 uint32_t ExpectedIndex = NumImportedEvents; 421 for (auto &Event : Section.Events) { 422 if (Event.Index != ExpectedIndex) { 423 reportError("unexpected event index: " + Twine(Event.Index)); 424 return; 425 } 426 ++ExpectedIndex; 427 encodeULEB128(Event.Attribute, OS); 428 encodeULEB128(Event.SigIndex, OS); 429 } 430 } 431 432 void WasmWriter::writeSectionContent(raw_ostream &OS, 433 WasmYAML::GlobalSection &Section) { 434 encodeULEB128(Section.Globals.size(), OS); 435 uint32_t ExpectedIndex = NumImportedGlobals; 436 for (auto &Global : Section.Globals) { 437 if (Global.Index != ExpectedIndex) { 438 reportError("unexpected global index: " + Twine(Global.Index)); 439 return; 440 } 441 ++ExpectedIndex; 442 writeUint8(OS, Global.Type); 443 writeUint8(OS, Global.Mutable); 444 writeInitExpr(OS, Global.InitExpr); 445 } 446 } 447 448 void WasmWriter::writeSectionContent(raw_ostream &OS, 449 WasmYAML::ElemSection &Section) { 450 encodeULEB128(Section.Segments.size(), OS); 451 for (auto &Segment : Section.Segments) { 452 encodeULEB128(Segment.TableIndex, OS); 453 writeInitExpr(OS, Segment.Offset); 454 455 encodeULEB128(Segment.Functions.size(), OS); 456 for (auto &Function : Segment.Functions) 457 encodeULEB128(Function, OS); 458 } 459 } 460 461 void WasmWriter::writeSectionContent(raw_ostream &OS, 462 WasmYAML::CodeSection &Section) { 463 encodeULEB128(Section.Functions.size(), OS); 464 uint32_t ExpectedIndex = NumImportedFunctions; 465 for (auto &Func : Section.Functions) { 466 std::string OutString; 467 raw_string_ostream StringStream(OutString); 468 if (Func.Index != ExpectedIndex) { 469 reportError("unexpected function index: " + Twine(Func.Index)); 470 return; 471 } 472 ++ExpectedIndex; 473 474 encodeULEB128(Func.Locals.size(), StringStream); 475 for (auto &LocalDecl : Func.Locals) { 476 encodeULEB128(LocalDecl.Count, StringStream); 477 writeUint8(StringStream, LocalDecl.Type); 478 } 479 480 Func.Body.writeAsBinary(StringStream); 481 482 // Write the section size followed by the content 483 StringStream.flush(); 484 encodeULEB128(OutString.size(), OS); 485 OS << OutString; 486 } 487 } 488 489 void WasmWriter::writeSectionContent(raw_ostream &OS, 490 WasmYAML::DataSection &Section) { 491 encodeULEB128(Section.Segments.size(), OS); 492 for (auto &Segment : Section.Segments) { 493 encodeULEB128(Segment.InitFlags, OS); 494 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX) 495 encodeULEB128(Segment.MemoryIndex, OS); 496 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) 497 writeInitExpr(OS, Segment.Offset); 498 encodeULEB128(Segment.Content.binary_size(), OS); 499 Segment.Content.writeAsBinary(OS); 500 } 501 } 502 503 void WasmWriter::writeSectionContent(raw_ostream &OS, 504 WasmYAML::DataCountSection &Section) { 505 encodeULEB128(Section.Count, OS); 506 } 507 508 void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec, 509 uint32_t SectionIndex) { 510 switch (Sec.Type) { 511 case wasm::WASM_SEC_CODE: 512 writeStringRef("reloc.CODE", OS); 513 break; 514 case wasm::WASM_SEC_DATA: 515 writeStringRef("reloc.DATA", OS); 516 break; 517 case wasm::WASM_SEC_CUSTOM: { 518 auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec); 519 writeStringRef(("reloc." + CustomSection->Name).str(), OS); 520 break; 521 } 522 default: 523 llvm_unreachable("not yet implemented"); 524 } 525 526 encodeULEB128(SectionIndex, OS); 527 encodeULEB128(Sec.Relocations.size(), OS); 528 529 for (auto Reloc : Sec.Relocations) { 530 writeUint8(OS, Reloc.Type); 531 encodeULEB128(Reloc.Offset, OS); 532 encodeULEB128(Reloc.Index, OS); 533 switch (Reloc.Type) { 534 case wasm::R_WASM_MEMORY_ADDR_LEB: 535 case wasm::R_WASM_MEMORY_ADDR_LEB64: 536 case wasm::R_WASM_MEMORY_ADDR_SLEB: 537 case wasm::R_WASM_MEMORY_ADDR_SLEB64: 538 case wasm::R_WASM_MEMORY_ADDR_I32: 539 case wasm::R_WASM_MEMORY_ADDR_I64: 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::EventSection>(Sec.get())) 578 writeSectionContent(StringStream, *S); 579 else if (auto S = dyn_cast<WasmYAML::GlobalSection>(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