Path: blob/main/contrib/llvm-project/llvm/lib/ObjectYAML/WasmEmitter.cpp
35233 views
//===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7///8/// \file9/// The Wasm component of yaml2obj.10///11//===----------------------------------------------------------------------===//12//1314#include "llvm/Object/Wasm.h"15#include "llvm/ObjectYAML/ObjectYAML.h"16#include "llvm/ObjectYAML/yaml2obj.h"17#include "llvm/Support/Endian.h"18#include "llvm/Support/LEB128.h"1920using namespace llvm;2122namespace {23/// This parses a yaml stream that represents a Wasm object file.24/// See docs/yaml2obj for the yaml scheema.25class WasmWriter {26public:27WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)28: Obj(Obj), ErrHandler(EH) {}29bool writeWasm(raw_ostream &OS);3031private:32void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,33uint32_t SectionIndex);3435void writeInitExpr(raw_ostream &OS, const WasmYAML::InitExpr &InitExpr);3637void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);38void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);39void writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);40void writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);41void writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);42void writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);43void writeSectionContent(raw_ostream &OS, WasmYAML::TagSection &Section);44void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);45void writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);46void writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);47void writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);48void writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);49void writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);50void writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);5152// Custom section types53void writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);54void writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);55void writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);56void writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);57void writeSectionContent(raw_ostream &OS,58WasmYAML::TargetFeaturesSection &Section);59WasmYAML::Object &Obj;60uint32_t NumImportedFunctions = 0;61uint32_t NumImportedGlobals = 0;62uint32_t NumImportedTables = 0;63uint32_t NumImportedTags = 0;6465bool HasError = false;66yaml::ErrorHandler ErrHandler;67void reportError(const Twine &Msg);68};6970class SubSectionWriter {71raw_ostream &OS;72std::string OutString;73raw_string_ostream StringStream;7475public:76SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}7778void done() {79StringStream.flush();80encodeULEB128(OutString.size(), OS);81OS << OutString;82OutString.clear();83}8485raw_ostream &getStream() { return StringStream; }86};8788} // end anonymous namespace8990static int writeUint64(raw_ostream &OS, uint64_t Value) {91char Data[sizeof(Value)];92support::endian::write64le(Data, Value);93OS.write(Data, sizeof(Data));94return 0;95}9697static int writeUint32(raw_ostream &OS, uint32_t Value) {98char Data[sizeof(Value)];99support::endian::write32le(Data, Value);100OS.write(Data, sizeof(Data));101return 0;102}103104static int writeUint8(raw_ostream &OS, uint8_t Value) {105char Data[sizeof(Value)];106memcpy(Data, &Value, sizeof(Data));107OS.write(Data, sizeof(Data));108return 0;109}110111static int writeStringRef(const StringRef &Str, raw_ostream &OS) {112encodeULEB128(Str.size(), OS);113OS << Str;114return 0;115}116117static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {118writeUint8(OS, Lim.Flags);119encodeULEB128(Lim.Minimum, OS);120if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)121encodeULEB128(Lim.Maximum, OS);122return 0;123}124125void WasmWriter::reportError(const Twine &Msg) {126ErrHandler(Msg);127HasError = true;128}129130void WasmWriter::writeInitExpr(raw_ostream &OS,131const WasmYAML::InitExpr &InitExpr) {132if (InitExpr.Extended) {133InitExpr.Body.writeAsBinary(OS);134} else {135writeUint8(OS, InitExpr.Inst.Opcode);136switch (InitExpr.Inst.Opcode) {137case wasm::WASM_OPCODE_I32_CONST:138encodeSLEB128(InitExpr.Inst.Value.Int32, OS);139break;140case wasm::WASM_OPCODE_I64_CONST:141encodeSLEB128(InitExpr.Inst.Value.Int64, OS);142break;143case wasm::WASM_OPCODE_F32_CONST:144writeUint32(OS, InitExpr.Inst.Value.Float32);145break;146case wasm::WASM_OPCODE_F64_CONST:147writeUint64(OS, InitExpr.Inst.Value.Float64);148break;149case wasm::WASM_OPCODE_GLOBAL_GET:150encodeULEB128(InitExpr.Inst.Value.Global, OS);151break;152default:153reportError("unknown opcode in init_expr: " +154Twine(InitExpr.Inst.Opcode));155return;156}157writeUint8(OS, wasm::WASM_OPCODE_END);158}159}160161void WasmWriter::writeSectionContent(raw_ostream &OS,162WasmYAML::DylinkSection &Section) {163writeStringRef(Section.Name, OS);164165writeUint8(OS, wasm::WASM_DYLINK_MEM_INFO);166SubSectionWriter SubSection(OS);167raw_ostream &SubOS = SubSection.getStream();168encodeULEB128(Section.MemorySize, SubOS);169encodeULEB128(Section.MemoryAlignment, SubOS);170encodeULEB128(Section.TableSize, SubOS);171encodeULEB128(Section.TableAlignment, SubOS);172SubSection.done();173174if (Section.Needed.size()) {175writeUint8(OS, wasm::WASM_DYLINK_NEEDED);176raw_ostream &SubOS = SubSection.getStream();177encodeULEB128(Section.Needed.size(), SubOS);178for (StringRef Needed : Section.Needed)179writeStringRef(Needed, SubOS);180SubSection.done();181}182}183184void WasmWriter::writeSectionContent(raw_ostream &OS,185WasmYAML::LinkingSection &Section) {186writeStringRef(Section.Name, OS);187encodeULEB128(Section.Version, OS);188189SubSectionWriter SubSection(OS);190191// SYMBOL_TABLE subsection192if (Section.SymbolTable.size()) {193writeUint8(OS, wasm::WASM_SYMBOL_TABLE);194encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());195for (auto Sym : llvm::enumerate(Section.SymbolTable)) {196const WasmYAML::SymbolInfo &Info = Sym.value();197assert(Info.Index == Sym.index());198writeUint8(SubSection.getStream(), Info.Kind);199encodeULEB128(Info.Flags, SubSection.getStream());200switch (Info.Kind) {201case wasm::WASM_SYMBOL_TYPE_FUNCTION:202case wasm::WASM_SYMBOL_TYPE_GLOBAL:203case wasm::WASM_SYMBOL_TYPE_TABLE:204case wasm::WASM_SYMBOL_TYPE_TAG:205encodeULEB128(Info.ElementIndex, SubSection.getStream());206if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||207(Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)208writeStringRef(Info.Name, SubSection.getStream());209break;210case wasm::WASM_SYMBOL_TYPE_DATA:211writeStringRef(Info.Name, SubSection.getStream());212if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {213encodeULEB128(Info.DataRef.Segment, SubSection.getStream());214encodeULEB128(Info.DataRef.Offset, SubSection.getStream());215encodeULEB128(Info.DataRef.Size, SubSection.getStream());216}217break;218case wasm::WASM_SYMBOL_TYPE_SECTION:219encodeULEB128(Info.ElementIndex, SubSection.getStream());220break;221default:222llvm_unreachable("unexpected kind");223}224}225226SubSection.done();227}228229// SEGMENT_NAMES subsection230if (Section.SegmentInfos.size()) {231writeUint8(OS, wasm::WASM_SEGMENT_INFO);232encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());233for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {234writeStringRef(SegmentInfo.Name, SubSection.getStream());235encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());236encodeULEB128(SegmentInfo.Flags, SubSection.getStream());237}238SubSection.done();239}240241// INIT_FUNCS subsection242if (Section.InitFunctions.size()) {243writeUint8(OS, wasm::WASM_INIT_FUNCS);244encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());245for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {246encodeULEB128(Func.Priority, SubSection.getStream());247encodeULEB128(Func.Symbol, SubSection.getStream());248}249SubSection.done();250}251252// COMDAT_INFO subsection253if (Section.Comdats.size()) {254writeUint8(OS, wasm::WASM_COMDAT_INFO);255encodeULEB128(Section.Comdats.size(), SubSection.getStream());256for (const auto &C : Section.Comdats) {257writeStringRef(C.Name, SubSection.getStream());258encodeULEB128(0, SubSection.getStream()); // flags for future use259encodeULEB128(C.Entries.size(), SubSection.getStream());260for (const WasmYAML::ComdatEntry &Entry : C.Entries) {261writeUint8(SubSection.getStream(), Entry.Kind);262encodeULEB128(Entry.Index, SubSection.getStream());263}264}265SubSection.done();266}267}268269void WasmWriter::writeSectionContent(raw_ostream &OS,270WasmYAML::NameSection &Section) {271writeStringRef(Section.Name, OS);272if (Section.FunctionNames.size()) {273writeUint8(OS, wasm::WASM_NAMES_FUNCTION);274275SubSectionWriter SubSection(OS);276277encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());278for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {279encodeULEB128(NameEntry.Index, SubSection.getStream());280writeStringRef(NameEntry.Name, SubSection.getStream());281}282283SubSection.done();284}285if (Section.GlobalNames.size()) {286writeUint8(OS, wasm::WASM_NAMES_GLOBAL);287288SubSectionWriter SubSection(OS);289290encodeULEB128(Section.GlobalNames.size(), SubSection.getStream());291for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {292encodeULEB128(NameEntry.Index, SubSection.getStream());293writeStringRef(NameEntry.Name, SubSection.getStream());294}295296SubSection.done();297}298if (Section.DataSegmentNames.size()) {299writeUint8(OS, wasm::WASM_NAMES_DATA_SEGMENT);300301SubSectionWriter SubSection(OS);302303encodeULEB128(Section.DataSegmentNames.size(), SubSection.getStream());304for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {305encodeULEB128(NameEntry.Index, SubSection.getStream());306writeStringRef(NameEntry.Name, SubSection.getStream());307}308309SubSection.done();310}311}312313void WasmWriter::writeSectionContent(raw_ostream &OS,314WasmYAML::ProducersSection &Section) {315writeStringRef(Section.Name, OS);316int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +317int(!Section.SDKs.empty());318if (Fields == 0)319return;320encodeULEB128(Fields, OS);321for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),322std::make_pair(StringRef("processed-by"), &Section.Tools),323std::make_pair(StringRef("sdk"), &Section.SDKs)}) {324if (Field.second->empty())325continue;326writeStringRef(Field.first, OS);327encodeULEB128(Field.second->size(), OS);328for (auto &Entry : *Field.second) {329writeStringRef(Entry.Name, OS);330writeStringRef(Entry.Version, OS);331}332}333}334335void WasmWriter::writeSectionContent(raw_ostream &OS,336WasmYAML::TargetFeaturesSection &Section) {337writeStringRef(Section.Name, OS);338encodeULEB128(Section.Features.size(), OS);339for (auto &E : Section.Features) {340writeUint8(OS, E.Prefix);341writeStringRef(E.Name, OS);342}343}344345void WasmWriter::writeSectionContent(raw_ostream &OS,346WasmYAML::CustomSection &Section) {347if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {348writeSectionContent(OS, *S);349} else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {350writeSectionContent(OS, *S);351} else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {352writeSectionContent(OS, *S);353} else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {354writeSectionContent(OS, *S);355} else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {356writeSectionContent(OS, *S);357} else {358writeStringRef(Section.Name, OS);359Section.Payload.writeAsBinary(OS);360}361}362363void WasmWriter::writeSectionContent(raw_ostream &OS,364WasmYAML::TypeSection &Section) {365encodeULEB128(Section.Signatures.size(), OS);366uint32_t ExpectedIndex = 0;367for (const WasmYAML::Signature &Sig : Section.Signatures) {368if (Sig.Index != ExpectedIndex) {369reportError("unexpected type index: " + Twine(Sig.Index));370return;371}372++ExpectedIndex;373writeUint8(OS, Sig.Form);374encodeULEB128(Sig.ParamTypes.size(), OS);375for (auto ParamType : Sig.ParamTypes)376writeUint8(OS, ParamType);377encodeULEB128(Sig.ReturnTypes.size(), OS);378for (auto ReturnType : Sig.ReturnTypes)379writeUint8(OS, ReturnType);380}381}382383void WasmWriter::writeSectionContent(raw_ostream &OS,384WasmYAML::ImportSection &Section) {385encodeULEB128(Section.Imports.size(), OS);386for (const WasmYAML::Import &Import : Section.Imports) {387writeStringRef(Import.Module, OS);388writeStringRef(Import.Field, OS);389writeUint8(OS, Import.Kind);390switch (Import.Kind) {391case wasm::WASM_EXTERNAL_FUNCTION:392encodeULEB128(Import.SigIndex, OS);393NumImportedFunctions++;394break;395case wasm::WASM_EXTERNAL_GLOBAL:396writeUint8(OS, Import.GlobalImport.Type);397writeUint8(OS, Import.GlobalImport.Mutable);398NumImportedGlobals++;399break;400case wasm::WASM_EXTERNAL_TAG:401writeUint8(OS, 0); // Reserved 'attribute' field402encodeULEB128(Import.SigIndex, OS);403NumImportedTags++;404break;405case wasm::WASM_EXTERNAL_MEMORY:406writeLimits(Import.Memory, OS);407break;408case wasm::WASM_EXTERNAL_TABLE:409writeUint8(OS, Import.TableImport.ElemType);410writeLimits(Import.TableImport.TableLimits, OS);411NumImportedTables++;412break;413default:414reportError("unknown import type: " +Twine(Import.Kind));415return;416}417}418}419420void WasmWriter::writeSectionContent(raw_ostream &OS,421WasmYAML::FunctionSection &Section) {422encodeULEB128(Section.FunctionTypes.size(), OS);423for (uint32_t FuncType : Section.FunctionTypes)424encodeULEB128(FuncType, OS);425}426427void WasmWriter::writeSectionContent(raw_ostream &OS,428WasmYAML::ExportSection &Section) {429encodeULEB128(Section.Exports.size(), OS);430for (const WasmYAML::Export &Export : Section.Exports) {431writeStringRef(Export.Name, OS);432writeUint8(OS, Export.Kind);433encodeULEB128(Export.Index, OS);434}435}436437void WasmWriter::writeSectionContent(raw_ostream &OS,438WasmYAML::StartSection &Section) {439encodeULEB128(Section.StartFunction, OS);440}441442void WasmWriter::writeSectionContent(raw_ostream &OS,443WasmYAML::TableSection &Section) {444encodeULEB128(Section.Tables.size(), OS);445uint32_t ExpectedIndex = NumImportedTables;446for (auto &Table : Section.Tables) {447if (Table.Index != ExpectedIndex) {448reportError("unexpected table index: " + Twine(Table.Index));449return;450}451++ExpectedIndex;452writeUint8(OS, Table.ElemType);453writeLimits(Table.TableLimits, OS);454}455}456457void WasmWriter::writeSectionContent(raw_ostream &OS,458WasmYAML::MemorySection &Section) {459encodeULEB128(Section.Memories.size(), OS);460for (const WasmYAML::Limits &Mem : Section.Memories)461writeLimits(Mem, OS);462}463464void WasmWriter::writeSectionContent(raw_ostream &OS,465WasmYAML::TagSection &Section) {466encodeULEB128(Section.TagTypes.size(), OS);467for (uint32_t TagType : Section.TagTypes) {468writeUint8(OS, 0); // Reserved 'attribute' field469encodeULEB128(TagType, OS);470}471}472473void WasmWriter::writeSectionContent(raw_ostream &OS,474WasmYAML::GlobalSection &Section) {475encodeULEB128(Section.Globals.size(), OS);476uint32_t ExpectedIndex = NumImportedGlobals;477for (auto &Global : Section.Globals) {478if (Global.Index != ExpectedIndex) {479reportError("unexpected global index: " + Twine(Global.Index));480return;481}482++ExpectedIndex;483writeUint8(OS, Global.Type);484writeUint8(OS, Global.Mutable);485writeInitExpr(OS, Global.Init);486}487}488489void WasmWriter::writeSectionContent(raw_ostream &OS,490WasmYAML::ElemSection &Section) {491encodeULEB128(Section.Segments.size(), OS);492for (auto &Segment : Section.Segments) {493encodeULEB128(Segment.Flags, OS);494if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)495encodeULEB128(Segment.TableNumber, OS);496497writeInitExpr(OS, Segment.Offset);498499if (Segment.Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {500// We only support active function table initializers, for which the elem501// kind is specified to be written as 0x00 and interpreted to mean502// "funcref".503if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {504reportError("unexpected elemkind: " + Twine(Segment.ElemKind));505return;506}507const uint8_t ElemKind = 0;508writeUint8(OS, ElemKind);509}510511encodeULEB128(Segment.Functions.size(), OS);512for (auto &Function : Segment.Functions)513encodeULEB128(Function, OS);514}515}516517void WasmWriter::writeSectionContent(raw_ostream &OS,518WasmYAML::CodeSection &Section) {519encodeULEB128(Section.Functions.size(), OS);520uint32_t ExpectedIndex = NumImportedFunctions;521for (auto &Func : Section.Functions) {522std::string OutString;523raw_string_ostream StringStream(OutString);524if (Func.Index != ExpectedIndex) {525reportError("unexpected function index: " + Twine(Func.Index));526return;527}528++ExpectedIndex;529530encodeULEB128(Func.Locals.size(), StringStream);531for (auto &LocalDecl : Func.Locals) {532encodeULEB128(LocalDecl.Count, StringStream);533writeUint8(StringStream, LocalDecl.Type);534}535536Func.Body.writeAsBinary(StringStream);537538// Write the section size followed by the content539StringStream.flush();540encodeULEB128(OutString.size(), OS);541OS << OutString;542}543}544545void WasmWriter::writeSectionContent(raw_ostream &OS,546WasmYAML::DataSection &Section) {547encodeULEB128(Section.Segments.size(), OS);548for (auto &Segment : Section.Segments) {549encodeULEB128(Segment.InitFlags, OS);550if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)551encodeULEB128(Segment.MemoryIndex, OS);552if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0)553writeInitExpr(OS, Segment.Offset);554encodeULEB128(Segment.Content.binary_size(), OS);555Segment.Content.writeAsBinary(OS);556}557}558559void WasmWriter::writeSectionContent(raw_ostream &OS,560WasmYAML::DataCountSection &Section) {561encodeULEB128(Section.Count, OS);562}563564void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,565uint32_t SectionIndex) {566switch (Sec.Type) {567case wasm::WASM_SEC_CODE:568writeStringRef("reloc.CODE", OS);569break;570case wasm::WASM_SEC_DATA:571writeStringRef("reloc.DATA", OS);572break;573case wasm::WASM_SEC_CUSTOM: {574auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);575writeStringRef(("reloc." + CustomSection->Name).str(), OS);576break;577}578default:579llvm_unreachable("not yet implemented");580}581582encodeULEB128(SectionIndex, OS);583encodeULEB128(Sec.Relocations.size(), OS);584585for (auto Reloc : Sec.Relocations) {586writeUint8(OS, Reloc.Type);587encodeULEB128(Reloc.Offset, OS);588encodeULEB128(Reloc.Index, OS);589if (wasm::relocTypeHasAddend(Reloc.Type))590encodeSLEB128(Reloc.Addend, OS);591}592}593594bool WasmWriter::writeWasm(raw_ostream &OS) {595// Write headers596OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));597writeUint32(OS, Obj.Header.Version);598599// Write each section600llvm::object::WasmSectionOrderChecker Checker;601for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {602StringRef SecName = "";603if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))604SecName = S->Name;605if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {606reportError("out of order section type: " + Twine(Sec->Type));607return false;608}609encodeULEB128(Sec->Type, OS);610std::string OutString;611raw_string_ostream StringStream(OutString);612if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))613writeSectionContent(StringStream, *S);614else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))615writeSectionContent(StringStream, *S);616else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))617writeSectionContent(StringStream, *S);618else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))619writeSectionContent(StringStream, *S);620else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))621writeSectionContent(StringStream, *S);622else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))623writeSectionContent(StringStream, *S);624else if (auto S = dyn_cast<WasmYAML::TagSection>(Sec.get()))625writeSectionContent(StringStream, *S);626else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))627writeSectionContent(StringStream, *S);628else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))629writeSectionContent(StringStream, *S);630else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))631writeSectionContent(StringStream, *S);632else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))633writeSectionContent(StringStream, *S);634else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))635writeSectionContent(StringStream, *S);636else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))637writeSectionContent(StringStream, *S);638else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))639writeSectionContent(StringStream, *S);640else641reportError("unknown section type: " + Twine(Sec->Type));642643if (HasError)644return false;645646StringStream.flush();647648unsigned HeaderSecSizeEncodingLen =649Sec->HeaderSecSizeEncodingLen ? *Sec->HeaderSecSizeEncodingLen : 5;650unsigned RequiredLen = getULEB128Size(OutString.size());651// Wasm spec does not allow LEBs larger than 5 bytes652assert(RequiredLen <= 5);653if (HeaderSecSizeEncodingLen < RequiredLen) {654reportError("section header length can't be encoded in a LEB of size " +655Twine(HeaderSecSizeEncodingLen));656return false;657}658// Write the section size followed by the content659encodeULEB128(OutString.size(), OS, HeaderSecSizeEncodingLen);660OS << OutString;661}662663// write reloc sections for any section that have relocations664uint32_t SectionIndex = 0;665for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {666if (Sec->Relocations.empty()) {667SectionIndex++;668continue;669}670671writeUint8(OS, wasm::WASM_SEC_CUSTOM);672std::string OutString;673raw_string_ostream StringStream(OutString);674writeRelocSection(StringStream, *Sec, SectionIndex++);675StringStream.flush();676677encodeULEB128(OutString.size(), OS);678OS << OutString;679}680681return true;682}683684namespace llvm {685namespace yaml {686687bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {688WasmWriter Writer(Doc, EH);689return Writer.writeWasm(Out);690}691692} // namespace yaml693} // namespace llvm694695696