brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.1 KiB · 9052b43 Raw
704 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// 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 21using namespace llvm;22 23namespace {24/// This parses a yaml stream that represents a Wasm object file.25/// See docs/yaml2obj for the yaml scheema.26class WasmWriter {27public:28  WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)29      : Obj(Obj), ErrHandler(EH) {}30  bool writeWasm(raw_ostream &OS);31 32private:33  void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,34                         uint32_t SectionIndex);35 36  void writeInitExpr(raw_ostream &OS, const WasmYAML::InitExpr &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::TagSection &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 types54  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 NumImportedTables = 0;64  uint32_t NumImportedTags = 0;65 66  bool HasError = false;67  yaml::ErrorHandler ErrHandler;68  void reportError(const Twine &Msg);69};70 71class SubSectionWriter {72  raw_ostream &OS;73  std::string OutString;74  raw_string_ostream StringStream;75 76public:77  SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}78 79  void done() {80    StringStream.flush();81    encodeULEB128(OutString.size(), OS);82    OS << OutString;83    OutString.clear();84  }85 86  raw_ostream &getStream() { return StringStream; }87};88 89} // end anonymous namespace90 91static int writeUint64(raw_ostream &OS, uint64_t Value) {92  char Data[sizeof(Value)];93  support::endian::write64le(Data, Value);94  OS.write(Data, sizeof(Data));95  return 0;96}97 98static int writeUint32(raw_ostream &OS, uint32_t Value) {99  char Data[sizeof(Value)];100  support::endian::write32le(Data, Value);101  OS.write(Data, sizeof(Data));102  return 0;103}104 105static int writeUint8(raw_ostream &OS, uint8_t Value) {106  char Data[sizeof(Value)];107  memcpy(Data, &Value, sizeof(Data));108  OS.write(Data, sizeof(Data));109  return 0;110}111 112static int writeStringRef(const StringRef &Str, raw_ostream &OS) {113  encodeULEB128(Str.size(), OS);114  OS << Str;115  return 0;116}117 118static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {119  writeUint8(OS, Lim.Flags);120  encodeULEB128(Lim.Minimum, OS);121  if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)122    encodeULEB128(Lim.Maximum, OS);123  return 0;124}125 126void WasmWriter::reportError(const Twine &Msg) {127  ErrHandler(Msg);128  HasError = true;129}130 131void WasmWriter::writeInitExpr(raw_ostream &OS,132                               const WasmYAML::InitExpr &InitExpr) {133  if (InitExpr.Extended) {134    InitExpr.Body.writeAsBinary(OS);135  } else {136    writeUint8(OS, InitExpr.Inst.Opcode);137    switch (InitExpr.Inst.Opcode) {138    case wasm::WASM_OPCODE_I32_CONST:139      encodeSLEB128(InitExpr.Inst.Value.Int32, OS);140      break;141    case wasm::WASM_OPCODE_I64_CONST:142      encodeSLEB128(InitExpr.Inst.Value.Int64, OS);143      break;144    case wasm::WASM_OPCODE_F32_CONST:145      writeUint32(OS, InitExpr.Inst.Value.Float32);146      break;147    case wasm::WASM_OPCODE_F64_CONST:148      writeUint64(OS, InitExpr.Inst.Value.Float64);149      break;150    case wasm::WASM_OPCODE_GLOBAL_GET:151      encodeULEB128(InitExpr.Inst.Value.Global, OS);152      break;153    default:154      reportError("unknown opcode in init_expr: " +155                  Twine(InitExpr.Inst.Opcode));156      return;157    }158    writeUint8(OS, wasm::WASM_OPCODE_END);159  }160}161 162void WasmWriter::writeSectionContent(raw_ostream &OS,163                                     WasmYAML::DylinkSection &Section) {164  writeStringRef(Section.Name, OS);165 166  writeUint8(OS, wasm::WASM_DYLINK_MEM_INFO);167  SubSectionWriter SubSection(OS);168  raw_ostream &SubOS = SubSection.getStream();169  encodeULEB128(Section.MemorySize, SubOS);170  encodeULEB128(Section.MemoryAlignment, SubOS);171  encodeULEB128(Section.TableSize, SubOS);172  encodeULEB128(Section.TableAlignment, SubOS);173  SubSection.done();174 175  if (Section.Needed.size()) {176    writeUint8(OS, wasm::WASM_DYLINK_NEEDED);177    raw_ostream &SubOS = SubSection.getStream();178    encodeULEB128(Section.Needed.size(), SubOS);179    for (StringRef Needed : Section.Needed)180      writeStringRef(Needed, SubOS);181    SubSection.done();182  }183  if (Section.RuntimePath.size()) {184    writeUint8(OS, wasm::WASM_DYLINK_RUNTIME_PATH);185    raw_ostream &SubOS = SubSection.getStream();186    encodeULEB128(Section.RuntimePath.size(), SubOS);187    for (StringRef Path : Section.RuntimePath)188      writeStringRef(Path, SubOS);189    SubSection.done();190  }191}192 193void WasmWriter::writeSectionContent(raw_ostream &OS,194                                     WasmYAML::LinkingSection &Section) {195  writeStringRef(Section.Name, OS);196  encodeULEB128(Section.Version, OS);197 198  SubSectionWriter SubSection(OS);199 200  // SYMBOL_TABLE subsection201  if (Section.SymbolTable.size()) {202    writeUint8(OS, wasm::WASM_SYMBOL_TABLE);203    encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());204    for (auto Sym : llvm::enumerate(Section.SymbolTable)) {205      const WasmYAML::SymbolInfo &Info = Sym.value();206      assert(Info.Index == Sym.index());207      writeUint8(SubSection.getStream(), Info.Kind);208      encodeULEB128(Info.Flags, SubSection.getStream());209      switch (Info.Kind) {210      case wasm::WASM_SYMBOL_TYPE_FUNCTION:211      case wasm::WASM_SYMBOL_TYPE_GLOBAL:212      case wasm::WASM_SYMBOL_TYPE_TABLE:213      case wasm::WASM_SYMBOL_TYPE_TAG:214        encodeULEB128(Info.ElementIndex, SubSection.getStream());215        if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||216            (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)217          writeStringRef(Info.Name, SubSection.getStream());218        break;219      case wasm::WASM_SYMBOL_TYPE_DATA:220        writeStringRef(Info.Name, SubSection.getStream());221        if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {222          encodeULEB128(Info.DataRef.Segment, SubSection.getStream());223          encodeULEB128(Info.DataRef.Offset, SubSection.getStream());224          encodeULEB128(Info.DataRef.Size, SubSection.getStream());225        }226        break;227      case wasm::WASM_SYMBOL_TYPE_SECTION:228        encodeULEB128(Info.ElementIndex, SubSection.getStream());229        break;230      default:231        llvm_unreachable("unexpected kind");232      }233    }234 235    SubSection.done();236  }237 238  // SEGMENT_NAMES subsection239  if (Section.SegmentInfos.size()) {240    writeUint8(OS, wasm::WASM_SEGMENT_INFO);241    encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());242    for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {243      writeStringRef(SegmentInfo.Name, SubSection.getStream());244      encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());245      encodeULEB128(SegmentInfo.Flags, SubSection.getStream());246    }247    SubSection.done();248  }249 250  // INIT_FUNCS subsection251  if (Section.InitFunctions.size()) {252    writeUint8(OS, wasm::WASM_INIT_FUNCS);253    encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());254    for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {255      encodeULEB128(Func.Priority, SubSection.getStream());256      encodeULEB128(Func.Symbol, SubSection.getStream());257    }258    SubSection.done();259  }260 261  // COMDAT_INFO subsection262  if (Section.Comdats.size()) {263    writeUint8(OS, wasm::WASM_COMDAT_INFO);264    encodeULEB128(Section.Comdats.size(), SubSection.getStream());265    for (const auto &C : Section.Comdats) {266      writeStringRef(C.Name, SubSection.getStream());267      encodeULEB128(0, SubSection.getStream()); // flags for future use268      encodeULEB128(C.Entries.size(), SubSection.getStream());269      for (const WasmYAML::ComdatEntry &Entry : C.Entries) {270        writeUint8(SubSection.getStream(), Entry.Kind);271        encodeULEB128(Entry.Index, SubSection.getStream());272      }273    }274    SubSection.done();275  }276}277 278void WasmWriter::writeSectionContent(raw_ostream &OS,279                                     WasmYAML::NameSection &Section) {280  writeStringRef(Section.Name, OS);281  if (Section.FunctionNames.size()) {282    writeUint8(OS, wasm::WASM_NAMES_FUNCTION);283 284    SubSectionWriter SubSection(OS);285 286    encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());287    for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {288      encodeULEB128(NameEntry.Index, SubSection.getStream());289      writeStringRef(NameEntry.Name, SubSection.getStream());290    }291 292    SubSection.done();293  }294  if (Section.GlobalNames.size()) {295    writeUint8(OS, wasm::WASM_NAMES_GLOBAL);296 297    SubSectionWriter SubSection(OS);298 299    encodeULEB128(Section.GlobalNames.size(), SubSection.getStream());300    for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {301      encodeULEB128(NameEntry.Index, SubSection.getStream());302      writeStringRef(NameEntry.Name, SubSection.getStream());303    }304 305    SubSection.done();306  }307  if (Section.DataSegmentNames.size()) {308    writeUint8(OS, wasm::WASM_NAMES_DATA_SEGMENT);309 310    SubSectionWriter SubSection(OS);311 312    encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());313    for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {314      encodeULEB128(NameEntry.Index, SubSection.getStream());315      writeStringRef(NameEntry.Name, SubSection.getStream());316    }317 318    SubSection.done();319  }320}321 322void WasmWriter::writeSectionContent(raw_ostream &OS,323                                     WasmYAML::ProducersSection &Section) {324  writeStringRef(Section.Name, OS);325  int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +326               int(!Section.SDKs.empty());327  if (Fields == 0)328    return;329  encodeULEB128(Fields, OS);330  for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),331                      std::make_pair(StringRef("processed-by"), &Section.Tools),332                      std::make_pair(StringRef("sdk"), &Section.SDKs)}) {333    if (Field.second->empty())334      continue;335    writeStringRef(Field.first, OS);336    encodeULEB128(Field.second->size(), OS);337    for (auto &Entry : *Field.second) {338      writeStringRef(Entry.Name, OS);339      writeStringRef(Entry.Version, OS);340    }341  }342}343 344void WasmWriter::writeSectionContent(raw_ostream &OS,345                                     WasmYAML::TargetFeaturesSection &Section) {346  writeStringRef(Section.Name, OS);347  encodeULEB128(Section.Features.size(), OS);348  for (auto &E : Section.Features) {349    writeUint8(OS, E.Prefix);350    writeStringRef(E.Name, OS);351  }352}353 354void WasmWriter::writeSectionContent(raw_ostream &OS,355                                     WasmYAML::CustomSection &Section) {356  if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {357    writeSectionContent(OS, *S);358  } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {359    writeSectionContent(OS, *S);360  } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {361    writeSectionContent(OS, *S);362  } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {363    writeSectionContent(OS, *S);364  } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {365    writeSectionContent(OS, *S);366  } else {367    writeStringRef(Section.Name, OS);368    Section.Payload.writeAsBinary(OS);369  }370}371 372void WasmWriter::writeSectionContent(raw_ostream &OS,373                                    WasmYAML::TypeSection &Section) {374  encodeULEB128(Section.Signatures.size(), OS);375  uint32_t ExpectedIndex = 0;376  for (const WasmYAML::Signature &Sig : Section.Signatures) {377    if (Sig.Index != ExpectedIndex) {378      reportError("unexpected type index: " + Twine(Sig.Index));379      return;380    }381    ++ExpectedIndex;382    writeUint8(OS, Sig.Form);383    encodeULEB128(Sig.ParamTypes.size(), OS);384    for (auto ParamType : Sig.ParamTypes)385      writeUint8(OS, ParamType);386    encodeULEB128(Sig.ReturnTypes.size(), OS);387    for (auto ReturnType : Sig.ReturnTypes)388      writeUint8(OS, ReturnType);389  }390}391 392void WasmWriter::writeSectionContent(raw_ostream &OS,393                                    WasmYAML::ImportSection &Section) {394  encodeULEB128(Section.Imports.size(), OS);395  for (const WasmYAML::Import &Import : Section.Imports) {396    writeStringRef(Import.Module, OS);397    writeStringRef(Import.Field, OS);398    writeUint8(OS, Import.Kind);399    switch (Import.Kind) {400    case wasm::WASM_EXTERNAL_FUNCTION:401      encodeULEB128(Import.SigIndex, OS);402      NumImportedFunctions++;403      break;404    case wasm::WASM_EXTERNAL_GLOBAL:405      writeUint8(OS, Import.GlobalImport.Type);406      writeUint8(OS, Import.GlobalImport.Mutable);407      NumImportedGlobals++;408      break;409    case wasm::WASM_EXTERNAL_TAG:410      writeUint8(OS, 0); // Reserved 'attribute' field411      encodeULEB128(Import.SigIndex, OS);412      NumImportedTags++;413      break;414    case wasm::WASM_EXTERNAL_MEMORY:415      writeLimits(Import.Memory, OS);416      break;417    case wasm::WASM_EXTERNAL_TABLE:418      writeUint8(OS, Import.TableImport.ElemType);419      writeLimits(Import.TableImport.TableLimits, OS);420      NumImportedTables++;421      break;422    default:423      reportError("unknown import type: " +Twine(Import.Kind));424      return;425    }426  }427}428 429void WasmWriter::writeSectionContent(raw_ostream &OS,430                                     WasmYAML::FunctionSection &Section) {431  encodeULEB128(Section.FunctionTypes.size(), OS);432  for (uint32_t FuncType : Section.FunctionTypes)433    encodeULEB128(FuncType, OS);434}435 436void WasmWriter::writeSectionContent(raw_ostream &OS,437                                    WasmYAML::ExportSection &Section) {438  encodeULEB128(Section.Exports.size(), OS);439  for (const WasmYAML::Export &Export : Section.Exports) {440    writeStringRef(Export.Name, OS);441    writeUint8(OS, Export.Kind);442    encodeULEB128(Export.Index, OS);443  }444}445 446void WasmWriter::writeSectionContent(raw_ostream &OS,447                                     WasmYAML::StartSection &Section) {448  encodeULEB128(Section.StartFunction, OS);449}450 451void WasmWriter::writeSectionContent(raw_ostream &OS,452                                     WasmYAML::TableSection &Section) {453  encodeULEB128(Section.Tables.size(), OS);454  uint32_t ExpectedIndex = NumImportedTables;455  for (auto &Table : Section.Tables) {456    if (Table.Index != ExpectedIndex) {457      reportError("unexpected table index: " + Twine(Table.Index));458      return;459    }460    ++ExpectedIndex;461    writeUint8(OS, Table.ElemType);462    writeLimits(Table.TableLimits, OS);463  }464}465 466void WasmWriter::writeSectionContent(raw_ostream &OS,467                                     WasmYAML::MemorySection &Section) {468  encodeULEB128(Section.Memories.size(), OS);469  for (const WasmYAML::Limits &Mem : Section.Memories)470    writeLimits(Mem, OS);471}472 473void WasmWriter::writeSectionContent(raw_ostream &OS,474                                     WasmYAML::TagSection &Section) {475  encodeULEB128(Section.TagTypes.size(), OS);476  for (uint32_t TagType : Section.TagTypes) {477    writeUint8(OS, 0); // Reserved 'attribute' field478    encodeULEB128(TagType, OS);479  }480}481 482void WasmWriter::writeSectionContent(raw_ostream &OS,483                                     WasmYAML::GlobalSection &Section) {484  encodeULEB128(Section.Globals.size(), OS);485  uint32_t ExpectedIndex = NumImportedGlobals;486  for (auto &Global : Section.Globals) {487    if (Global.Index != ExpectedIndex) {488      reportError("unexpected global index: " + Twine(Global.Index));489      return;490    }491    ++ExpectedIndex;492    writeUint8(OS, Global.Type);493    writeUint8(OS, Global.Mutable);494    writeInitExpr(OS, Global.Init);495  }496}497 498void WasmWriter::writeSectionContent(raw_ostream &OS,499                                     WasmYAML::ElemSection &Section) {500  encodeULEB128(Section.Segments.size(), OS);501  for (auto &Segment : Section.Segments) {502    encodeULEB128(Segment.Flags, OS);503    if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)504      encodeULEB128(Segment.TableNumber, OS);505 506    writeInitExpr(OS, Segment.Offset);507 508    if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC) {509      // We only support active function table initializers, for which the elem510      // kind is specified to be written as 0x00 and interpreted to mean511      // "funcref".512      if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {513        reportError("unexpected elemkind: " + Twine(Segment.ElemKind));514        return;515      }516      const uint8_t ElemKind = 0;517      writeUint8(OS, ElemKind);518    }519 520    encodeULEB128(Segment.Functions.size(), OS);521    for (auto &Function : Segment.Functions)522      encodeULEB128(Function, OS);523  }524}525 526void WasmWriter::writeSectionContent(raw_ostream &OS,527                                    WasmYAML::CodeSection &Section) {528  encodeULEB128(Section.Functions.size(), OS);529  uint32_t ExpectedIndex = NumImportedFunctions;530  for (auto &Func : Section.Functions) {531    std::string OutString;532    raw_string_ostream StringStream(OutString);533    if (Func.Index != ExpectedIndex) {534      reportError("unexpected function index: " + Twine(Func.Index));535      return;536    }537    ++ExpectedIndex;538 539    encodeULEB128(Func.Locals.size(), StringStream);540    for (auto &LocalDecl : Func.Locals) {541      encodeULEB128(LocalDecl.Count, StringStream);542      writeUint8(StringStream, LocalDecl.Type);543    }544 545    Func.Body.writeAsBinary(StringStream);546 547    // Write the section size followed by the content548    StringStream.flush();549    encodeULEB128(OutString.size(), OS);550    OS << OutString;551  }552}553 554void WasmWriter::writeSectionContent(raw_ostream &OS,555                                     WasmYAML::DataSection &Section) {556  encodeULEB128(Section.Segments.size(), OS);557  for (auto &Segment : Section.Segments) {558    encodeULEB128(Segment.InitFlags, OS);559    if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)560      encodeULEB128(Segment.MemoryIndex, OS);561    if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)562      writeInitExpr(OS, Segment.Offset);563    encodeULEB128(Segment.Content.binary_size(), OS);564    Segment.Content.writeAsBinary(OS);565  }566}567 568void WasmWriter::writeSectionContent(raw_ostream &OS,569                                     WasmYAML::DataCountSection &Section) {570  encodeULEB128(Section.Count, OS);571}572 573void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,574                                  uint32_t SectionIndex) {575  switch (Sec.Type) {576  case wasm::WASM_SEC_CODE:577    writeStringRef("reloc.CODE", OS);578    break;579  case wasm::WASM_SEC_DATA:580    writeStringRef("reloc.DATA", OS);581    break;582  case wasm::WASM_SEC_CUSTOM: {583    auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);584    writeStringRef(("reloc." + CustomSection->Name).str(), OS);585    break;586  }587  default:588    llvm_unreachable("not yet implemented");589  }590 591  encodeULEB128(SectionIndex, OS);592  encodeULEB128(Sec.Relocations.size(), OS);593 594  for (auto Reloc : Sec.Relocations) {595    writeUint8(OS, Reloc.Type);596    encodeULEB128(Reloc.Offset, OS);597    encodeULEB128(Reloc.Index, OS);598    if (wasm::relocTypeHasAddend(Reloc.Type))599      encodeSLEB128(Reloc.Addend, OS);600  }601}602 603bool WasmWriter::writeWasm(raw_ostream &OS) {604  // Write headers605  OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));606  writeUint32(OS, Obj.Header.Version);607 608  // Write each section609  llvm::object::WasmSectionOrderChecker Checker;610  for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {611    StringRef SecName = "";612    if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))613      SecName = S->Name;614    if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {615      reportError("out of order section type: " +616                  wasm::sectionTypeToString(Sec->Type));617      return false;618    }619    encodeULEB128(Sec->Type, OS);620    std::string OutString;621    raw_string_ostream StringStream(OutString);622    if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))623      writeSectionContent(StringStream, *S);624    else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))625      writeSectionContent(StringStream, *S);626    else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))627      writeSectionContent(StringStream, *S);628    else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))629      writeSectionContent(StringStream, *S);630    else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))631      writeSectionContent(StringStream, *S);632    else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))633      writeSectionContent(StringStream, *S);634    else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))635      writeSectionContent(StringStream, *S);636    else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))637      writeSectionContent(StringStream, *S);638    else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))639      writeSectionContent(StringStream, *S);640    else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))641      writeSectionContent(StringStream, *S);642    else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))643      writeSectionContent(StringStream, *S);644    else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))645      writeSectionContent(StringStream, *S);646    else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))647      writeSectionContent(StringStream, *S);648    else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))649      writeSectionContent(StringStream, *S);650    else651      reportError("unknown section type: " + Twine(Sec->Type));652 653    if (HasError)654      return false;655 656    StringStream.flush();657 658    unsigned HeaderSecSizeEncodingLen =659        Sec->HeaderSecSizeEncodingLen.value_or(5);660    unsigned RequiredLen = getULEB128Size(OutString.size());661    // Wasm spec does not allow LEBs larger than 5 bytes662    assert(RequiredLen <= 5);663    if (HeaderSecSizeEncodingLen < RequiredLen) {664      reportError("section header length can't be encoded in a LEB of size " +665                  Twine(HeaderSecSizeEncodingLen));666      return false;667    }668    // Write the section size followed by the content669    encodeULEB128(OutString.size(), OS, HeaderSecSizeEncodingLen);670    OS << OutString;671  }672 673  // write reloc sections for any section that have relocations674  uint32_t SectionIndex = 0;675  for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {676    if (Sec->Relocations.empty()) {677      SectionIndex++;678      continue;679    }680 681    writeUint8(OS, wasm::WASM_SEC_CUSTOM);682    std::string OutString;683    raw_string_ostream StringStream(OutString);684    writeRelocSection(StringStream, *Sec, SectionIndex++);685    StringStream.flush();686 687    encodeULEB128(OutString.size(), OS);688    OS << OutString;689  }690 691  return true;692}693 694namespace llvm {695namespace yaml {696 697bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {698  WasmWriter Writer(Doc, EH);699  return Writer.writeWasm(Out);700}701 702} // namespace yaml703} // namespace llvm704