1 //===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// The Wasm component of yaml2obj.
12 //===----------------------------------------------------------------------===//
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"
24 /// This parses a yaml stream that represents a Wasm object file.
25 /// See docs/yaml2obj for the yaml scheema.
28 WasmWriter(WasmYAML::Object
&Obj
, yaml::ErrorHandler EH
)
29 : Obj(Obj
), ErrHandler(EH
) {}
30 bool writeWasm(raw_ostream
&OS
);
33 void writeRelocSection(raw_ostream
&OS
, WasmYAML::Section
&Sec
,
34 uint32_t SectionIndex
);
36 void writeInitExpr(raw_ostream
&OS
, const WasmYAML::InitExpr
&InitExpr
);
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
);
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 NumImportedTables
= 0;
64 uint32_t NumImportedTags
= 0;
66 bool HasError
= false;
67 yaml::ErrorHandler ErrHandler
;
68 void reportError(const Twine
&Msg
);
71 class SubSectionWriter
{
73 std::string OutString
;
74 raw_string_ostream StringStream
;
77 SubSectionWriter(raw_ostream
&OS
) : OS(OS
), StringStream(OutString
) {}
81 encodeULEB128(OutString
.size(), OS
);
86 raw_ostream
&getStream() { return StringStream
; }
89 } // end anonymous namespace
91 static 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
));
98 static 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
));
105 static 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
));
112 static int writeStringRef(const StringRef
&Str
, raw_ostream
&OS
) {
113 encodeULEB128(Str
.size(), OS
);
118 static 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
);
126 void WasmWriter::reportError(const Twine
&Msg
) {
131 void WasmWriter::writeInitExpr(raw_ostream
&OS
,
132 const WasmYAML::InitExpr
&InitExpr
) {
133 if (InitExpr
.Extended
) {
134 InitExpr
.Body
.writeAsBinary(OS
);
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
);
141 case wasm::WASM_OPCODE_I64_CONST
:
142 encodeSLEB128(InitExpr
.Inst
.Value
.Int64
, OS
);
144 case wasm::WASM_OPCODE_F32_CONST
:
145 writeUint32(OS
, InitExpr
.Inst
.Value
.Float32
);
147 case wasm::WASM_OPCODE_F64_CONST
:
148 writeUint64(OS
, InitExpr
.Inst
.Value
.Float64
);
150 case wasm::WASM_OPCODE_GLOBAL_GET
:
151 encodeULEB128(InitExpr
.Inst
.Value
.Global
, OS
);
154 reportError("unknown opcode in init_expr: " +
155 Twine(InitExpr
.Inst
.Opcode
));
158 writeUint8(OS
, wasm::WASM_OPCODE_END
);
162 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
163 WasmYAML::DylinkSection
&Section
) {
164 writeStringRef(Section
.Name
, OS
);
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
);
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
);
185 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
186 WasmYAML::LinkingSection
&Section
) {
187 writeStringRef(Section
.Name
, OS
);
188 encodeULEB128(Section
.Version
, OS
);
190 SubSectionWriter
SubSection(OS
);
192 // SYMBOL_TABLE subsection
193 if (Section
.SymbolTable
.size()) {
194 writeUint8(OS
, wasm::WASM_SYMBOL_TABLE
);
195 encodeULEB128(Section
.SymbolTable
.size(), SubSection
.getStream());
196 for (auto Sym
: llvm::enumerate(Section
.SymbolTable
)) {
197 const WasmYAML::SymbolInfo
&Info
= Sym
.value();
198 assert(Info
.Index
== Sym
.index());
199 writeUint8(SubSection
.getStream(), Info
.Kind
);
200 encodeULEB128(Info
.Flags
, SubSection
.getStream());
202 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
203 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
204 case wasm::WASM_SYMBOL_TYPE_TABLE
:
205 case wasm::WASM_SYMBOL_TYPE_TAG
:
206 encodeULEB128(Info
.ElementIndex
, SubSection
.getStream());
207 if ((Info
.Flags
& wasm::WASM_SYMBOL_UNDEFINED
) == 0 ||
208 (Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0)
209 writeStringRef(Info
.Name
, SubSection
.getStream());
211 case wasm::WASM_SYMBOL_TYPE_DATA
:
212 writeStringRef(Info
.Name
, SubSection
.getStream());
213 if ((Info
.Flags
& wasm::WASM_SYMBOL_UNDEFINED
) == 0) {
214 encodeULEB128(Info
.DataRef
.Segment
, SubSection
.getStream());
215 encodeULEB128(Info
.DataRef
.Offset
, SubSection
.getStream());
216 encodeULEB128(Info
.DataRef
.Size
, SubSection
.getStream());
219 case wasm::WASM_SYMBOL_TYPE_SECTION
:
220 encodeULEB128(Info
.ElementIndex
, SubSection
.getStream());
223 llvm_unreachable("unexpected kind");
230 // SEGMENT_NAMES subsection
231 if (Section
.SegmentInfos
.size()) {
232 writeUint8(OS
, wasm::WASM_SEGMENT_INFO
);
233 encodeULEB128(Section
.SegmentInfos
.size(), SubSection
.getStream());
234 for (const WasmYAML::SegmentInfo
&SegmentInfo
: Section
.SegmentInfos
) {
235 writeStringRef(SegmentInfo
.Name
, SubSection
.getStream());
236 encodeULEB128(SegmentInfo
.Alignment
, SubSection
.getStream());
237 encodeULEB128(SegmentInfo
.Flags
, SubSection
.getStream());
242 // INIT_FUNCS subsection
243 if (Section
.InitFunctions
.size()) {
244 writeUint8(OS
, wasm::WASM_INIT_FUNCS
);
245 encodeULEB128(Section
.InitFunctions
.size(), SubSection
.getStream());
246 for (const WasmYAML::InitFunction
&Func
: Section
.InitFunctions
) {
247 encodeULEB128(Func
.Priority
, SubSection
.getStream());
248 encodeULEB128(Func
.Symbol
, SubSection
.getStream());
253 // COMDAT_INFO subsection
254 if (Section
.Comdats
.size()) {
255 writeUint8(OS
, wasm::WASM_COMDAT_INFO
);
256 encodeULEB128(Section
.Comdats
.size(), SubSection
.getStream());
257 for (const auto &C
: Section
.Comdats
) {
258 writeStringRef(C
.Name
, SubSection
.getStream());
259 encodeULEB128(0, SubSection
.getStream()); // flags for future use
260 encodeULEB128(C
.Entries
.size(), SubSection
.getStream());
261 for (const WasmYAML::ComdatEntry
&Entry
: C
.Entries
) {
262 writeUint8(SubSection
.getStream(), Entry
.Kind
);
263 encodeULEB128(Entry
.Index
, SubSection
.getStream());
270 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
271 WasmYAML::NameSection
&Section
) {
272 writeStringRef(Section
.Name
, OS
);
273 if (Section
.FunctionNames
.size()) {
274 writeUint8(OS
, wasm::WASM_NAMES_FUNCTION
);
276 SubSectionWriter
SubSection(OS
);
278 encodeULEB128(Section
.FunctionNames
.size(), SubSection
.getStream());
279 for (const WasmYAML::NameEntry
&NameEntry
: Section
.FunctionNames
) {
280 encodeULEB128(NameEntry
.Index
, SubSection
.getStream());
281 writeStringRef(NameEntry
.Name
, SubSection
.getStream());
286 if (Section
.GlobalNames
.size()) {
287 writeUint8(OS
, wasm::WASM_NAMES_GLOBAL
);
289 SubSectionWriter
SubSection(OS
);
291 encodeULEB128(Section
.GlobalNames
.size(), SubSection
.getStream());
292 for (const WasmYAML::NameEntry
&NameEntry
: Section
.GlobalNames
) {
293 encodeULEB128(NameEntry
.Index
, SubSection
.getStream());
294 writeStringRef(NameEntry
.Name
, SubSection
.getStream());
299 if (Section
.DataSegmentNames
.size()) {
300 writeUint8(OS
, wasm::WASM_NAMES_DATA_SEGMENT
);
302 SubSectionWriter
SubSection(OS
);
304 encodeULEB128(Section
.DataSegmentNames
.size(), SubSection
.getStream());
305 for (const WasmYAML::NameEntry
&NameEntry
: Section
.DataSegmentNames
) {
306 encodeULEB128(NameEntry
.Index
, SubSection
.getStream());
307 writeStringRef(NameEntry
.Name
, SubSection
.getStream());
314 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
315 WasmYAML::ProducersSection
&Section
) {
316 writeStringRef(Section
.Name
, OS
);
317 int Fields
= int(!Section
.Languages
.empty()) + int(!Section
.Tools
.empty()) +
318 int(!Section
.SDKs
.empty());
321 encodeULEB128(Fields
, OS
);
322 for (auto &Field
: {std::make_pair(StringRef("language"), &Section
.Languages
),
323 std::make_pair(StringRef("processed-by"), &Section
.Tools
),
324 std::make_pair(StringRef("sdk"), &Section
.SDKs
)}) {
325 if (Field
.second
->empty())
327 writeStringRef(Field
.first
, OS
);
328 encodeULEB128(Field
.second
->size(), OS
);
329 for (auto &Entry
: *Field
.second
) {
330 writeStringRef(Entry
.Name
, OS
);
331 writeStringRef(Entry
.Version
, OS
);
336 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
337 WasmYAML::TargetFeaturesSection
&Section
) {
338 writeStringRef(Section
.Name
, OS
);
339 encodeULEB128(Section
.Features
.size(), OS
);
340 for (auto &E
: Section
.Features
) {
341 writeUint8(OS
, E
.Prefix
);
342 writeStringRef(E
.Name
, OS
);
346 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
347 WasmYAML::CustomSection
&Section
) {
348 if (auto S
= dyn_cast
<WasmYAML::DylinkSection
>(&Section
)) {
349 writeSectionContent(OS
, *S
);
350 } else if (auto S
= dyn_cast
<WasmYAML::NameSection
>(&Section
)) {
351 writeSectionContent(OS
, *S
);
352 } else if (auto S
= dyn_cast
<WasmYAML::LinkingSection
>(&Section
)) {
353 writeSectionContent(OS
, *S
);
354 } else if (auto S
= dyn_cast
<WasmYAML::ProducersSection
>(&Section
)) {
355 writeSectionContent(OS
, *S
);
356 } else if (auto S
= dyn_cast
<WasmYAML::TargetFeaturesSection
>(&Section
)) {
357 writeSectionContent(OS
, *S
);
359 writeStringRef(Section
.Name
, OS
);
360 Section
.Payload
.writeAsBinary(OS
);
364 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
365 WasmYAML::TypeSection
&Section
) {
366 encodeULEB128(Section
.Signatures
.size(), OS
);
367 uint32_t ExpectedIndex
= 0;
368 for (const WasmYAML::Signature
&Sig
: Section
.Signatures
) {
369 if (Sig
.Index
!= ExpectedIndex
) {
370 reportError("unexpected type index: " + Twine(Sig
.Index
));
374 writeUint8(OS
, Sig
.Form
);
375 encodeULEB128(Sig
.ParamTypes
.size(), OS
);
376 for (auto ParamType
: Sig
.ParamTypes
)
377 writeUint8(OS
, ParamType
);
378 encodeULEB128(Sig
.ReturnTypes
.size(), OS
);
379 for (auto ReturnType
: Sig
.ReturnTypes
)
380 writeUint8(OS
, ReturnType
);
384 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
385 WasmYAML::ImportSection
&Section
) {
386 encodeULEB128(Section
.Imports
.size(), OS
);
387 for (const WasmYAML::Import
&Import
: Section
.Imports
) {
388 writeStringRef(Import
.Module
, OS
);
389 writeStringRef(Import
.Field
, OS
);
390 writeUint8(OS
, Import
.Kind
);
391 switch (Import
.Kind
) {
392 case wasm::WASM_EXTERNAL_FUNCTION
:
393 encodeULEB128(Import
.SigIndex
, OS
);
394 NumImportedFunctions
++;
396 case wasm::WASM_EXTERNAL_GLOBAL
:
397 writeUint8(OS
, Import
.GlobalImport
.Type
);
398 writeUint8(OS
, Import
.GlobalImport
.Mutable
);
399 NumImportedGlobals
++;
401 case wasm::WASM_EXTERNAL_TAG
:
402 writeUint8(OS
, 0); // Reserved 'attribute' field
403 encodeULEB128(Import
.SigIndex
, OS
);
406 case wasm::WASM_EXTERNAL_MEMORY
:
407 writeLimits(Import
.Memory
, OS
);
409 case wasm::WASM_EXTERNAL_TABLE
:
410 writeUint8(OS
, Import
.TableImport
.ElemType
);
411 writeLimits(Import
.TableImport
.TableLimits
, OS
);
415 reportError("unknown import type: " +Twine(Import
.Kind
));
421 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
422 WasmYAML::FunctionSection
&Section
) {
423 encodeULEB128(Section
.FunctionTypes
.size(), OS
);
424 for (uint32_t FuncType
: Section
.FunctionTypes
)
425 encodeULEB128(FuncType
, OS
);
428 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
429 WasmYAML::ExportSection
&Section
) {
430 encodeULEB128(Section
.Exports
.size(), OS
);
431 for (const WasmYAML::Export
&Export
: Section
.Exports
) {
432 writeStringRef(Export
.Name
, OS
);
433 writeUint8(OS
, Export
.Kind
);
434 encodeULEB128(Export
.Index
, OS
);
438 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
439 WasmYAML::StartSection
&Section
) {
440 encodeULEB128(Section
.StartFunction
, OS
);
443 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
444 WasmYAML::TableSection
&Section
) {
445 encodeULEB128(Section
.Tables
.size(), OS
);
446 uint32_t ExpectedIndex
= NumImportedTables
;
447 for (auto &Table
: Section
.Tables
) {
448 if (Table
.Index
!= ExpectedIndex
) {
449 reportError("unexpected table index: " + Twine(Table
.Index
));
453 writeUint8(OS
, Table
.ElemType
);
454 writeLimits(Table
.TableLimits
, OS
);
458 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
459 WasmYAML::MemorySection
&Section
) {
460 encodeULEB128(Section
.Memories
.size(), OS
);
461 for (const WasmYAML::Limits
&Mem
: Section
.Memories
)
462 writeLimits(Mem
, OS
);
465 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
466 WasmYAML::TagSection
&Section
) {
467 encodeULEB128(Section
.TagTypes
.size(), OS
);
468 for (uint32_t TagType
: Section
.TagTypes
) {
469 writeUint8(OS
, 0); // Reserved 'attribute' field
470 encodeULEB128(TagType
, OS
);
474 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
475 WasmYAML::GlobalSection
&Section
) {
476 encodeULEB128(Section
.Globals
.size(), OS
);
477 uint32_t ExpectedIndex
= NumImportedGlobals
;
478 for (auto &Global
: Section
.Globals
) {
479 if (Global
.Index
!= ExpectedIndex
) {
480 reportError("unexpected global index: " + Twine(Global
.Index
));
484 writeUint8(OS
, Global
.Type
);
485 writeUint8(OS
, Global
.Mutable
);
486 writeInitExpr(OS
, Global
.Init
);
490 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
491 WasmYAML::ElemSection
&Section
) {
492 encodeULEB128(Section
.Segments
.size(), OS
);
493 for (auto &Segment
: Section
.Segments
) {
494 encodeULEB128(Segment
.Flags
, OS
);
495 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
)
496 encodeULEB128(Segment
.TableNumber
, OS
);
498 writeInitExpr(OS
, Segment
.Offset
);
500 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
) {
501 // We only support active function table initializers, for which the elem
502 // kind is specified to be written as 0x00 and interpreted to mean
504 if (Segment
.ElemKind
!= uint32_t(wasm::ValType::FUNCREF
)) {
505 reportError("unexpected elemkind: " + Twine(Segment
.ElemKind
));
508 const uint8_t ElemKind
= 0;
509 writeUint8(OS
, ElemKind
);
512 encodeULEB128(Segment
.Functions
.size(), OS
);
513 for (auto &Function
: Segment
.Functions
)
514 encodeULEB128(Function
, OS
);
518 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
519 WasmYAML::CodeSection
&Section
) {
520 encodeULEB128(Section
.Functions
.size(), OS
);
521 uint32_t ExpectedIndex
= NumImportedFunctions
;
522 for (auto &Func
: Section
.Functions
) {
523 std::string OutString
;
524 raw_string_ostream
StringStream(OutString
);
525 if (Func
.Index
!= ExpectedIndex
) {
526 reportError("unexpected function index: " + Twine(Func
.Index
));
531 encodeULEB128(Func
.Locals
.size(), StringStream
);
532 for (auto &LocalDecl
: Func
.Locals
) {
533 encodeULEB128(LocalDecl
.Count
, StringStream
);
534 writeUint8(StringStream
, LocalDecl
.Type
);
537 Func
.Body
.writeAsBinary(StringStream
);
539 // Write the section size followed by the content
540 StringStream
.flush();
541 encodeULEB128(OutString
.size(), OS
);
546 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
547 WasmYAML::DataSection
&Section
) {
548 encodeULEB128(Section
.Segments
.size(), OS
);
549 for (auto &Segment
: Section
.Segments
) {
550 encodeULEB128(Segment
.InitFlags
, OS
);
551 if (Segment
.InitFlags
& wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX
)
552 encodeULEB128(Segment
.MemoryIndex
, OS
);
553 if ((Segment
.InitFlags
& wasm::WASM_DATA_SEGMENT_IS_PASSIVE
) == 0)
554 writeInitExpr(OS
, Segment
.Offset
);
555 encodeULEB128(Segment
.Content
.binary_size(), OS
);
556 Segment
.Content
.writeAsBinary(OS
);
560 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
561 WasmYAML::DataCountSection
&Section
) {
562 encodeULEB128(Section
.Count
, OS
);
565 void WasmWriter::writeRelocSection(raw_ostream
&OS
, WasmYAML::Section
&Sec
,
566 uint32_t SectionIndex
) {
568 case wasm::WASM_SEC_CODE
:
569 writeStringRef("reloc.CODE", OS
);
571 case wasm::WASM_SEC_DATA
:
572 writeStringRef("reloc.DATA", OS
);
574 case wasm::WASM_SEC_CUSTOM
: {
575 auto *CustomSection
= cast
<WasmYAML::CustomSection
>(&Sec
);
576 writeStringRef(("reloc." + CustomSection
->Name
).str(), OS
);
580 llvm_unreachable("not yet implemented");
583 encodeULEB128(SectionIndex
, OS
);
584 encodeULEB128(Sec
.Relocations
.size(), OS
);
586 for (auto Reloc
: Sec
.Relocations
) {
587 writeUint8(OS
, Reloc
.Type
);
588 encodeULEB128(Reloc
.Offset
, OS
);
589 encodeULEB128(Reloc
.Index
, OS
);
590 if (wasm::relocTypeHasAddend(Reloc
.Type
))
591 encodeSLEB128(Reloc
.Addend
, OS
);
595 bool WasmWriter::writeWasm(raw_ostream
&OS
) {
597 OS
.write(wasm::WasmMagic
, sizeof(wasm::WasmMagic
));
598 writeUint32(OS
, Obj
.Header
.Version
);
600 // Write each section
601 llvm::object::WasmSectionOrderChecker Checker
;
602 for (const std::unique_ptr
<WasmYAML::Section
> &Sec
: Obj
.Sections
) {
603 StringRef SecName
= "";
604 if (auto S
= dyn_cast
<WasmYAML::CustomSection
>(Sec
.get()))
606 if (!Checker
.isValidSectionOrder(Sec
->Type
, SecName
)) {
607 reportError("out of order section type: " +
608 wasm::sectionTypeToString(Sec
->Type
));
611 encodeULEB128(Sec
->Type
, OS
);
612 std::string OutString
;
613 raw_string_ostream
StringStream(OutString
);
614 if (auto S
= dyn_cast
<WasmYAML::CustomSection
>(Sec
.get()))
615 writeSectionContent(StringStream
, *S
);
616 else if (auto S
= dyn_cast
<WasmYAML::TypeSection
>(Sec
.get()))
617 writeSectionContent(StringStream
, *S
);
618 else if (auto S
= dyn_cast
<WasmYAML::ImportSection
>(Sec
.get()))
619 writeSectionContent(StringStream
, *S
);
620 else if (auto S
= dyn_cast
<WasmYAML::FunctionSection
>(Sec
.get()))
621 writeSectionContent(StringStream
, *S
);
622 else if (auto S
= dyn_cast
<WasmYAML::TableSection
>(Sec
.get()))
623 writeSectionContent(StringStream
, *S
);
624 else if (auto S
= dyn_cast
<WasmYAML::MemorySection
>(Sec
.get()))
625 writeSectionContent(StringStream
, *S
);
626 else if (auto S
= dyn_cast
<WasmYAML::TagSection
>(Sec
.get()))
627 writeSectionContent(StringStream
, *S
);
628 else if (auto S
= dyn_cast
<WasmYAML::GlobalSection
>(Sec
.get()))
629 writeSectionContent(StringStream
, *S
);
630 else if (auto S
= dyn_cast
<WasmYAML::ExportSection
>(Sec
.get()))
631 writeSectionContent(StringStream
, *S
);
632 else if (auto S
= dyn_cast
<WasmYAML::StartSection
>(Sec
.get()))
633 writeSectionContent(StringStream
, *S
);
634 else if (auto S
= dyn_cast
<WasmYAML::ElemSection
>(Sec
.get()))
635 writeSectionContent(StringStream
, *S
);
636 else if (auto S
= dyn_cast
<WasmYAML::CodeSection
>(Sec
.get()))
637 writeSectionContent(StringStream
, *S
);
638 else if (auto S
= dyn_cast
<WasmYAML::DataSection
>(Sec
.get()))
639 writeSectionContent(StringStream
, *S
);
640 else if (auto S
= dyn_cast
<WasmYAML::DataCountSection
>(Sec
.get()))
641 writeSectionContent(StringStream
, *S
);
643 reportError("unknown section type: " + Twine(Sec
->Type
));
648 StringStream
.flush();
650 unsigned HeaderSecSizeEncodingLen
=
651 Sec
->HeaderSecSizeEncodingLen
.value_or(5);
652 unsigned RequiredLen
= getULEB128Size(OutString
.size());
653 // Wasm spec does not allow LEBs larger than 5 bytes
654 assert(RequiredLen
<= 5);
655 if (HeaderSecSizeEncodingLen
< RequiredLen
) {
656 reportError("section header length can't be encoded in a LEB of size " +
657 Twine(HeaderSecSizeEncodingLen
));
660 // Write the section size followed by the content
661 encodeULEB128(OutString
.size(), OS
, HeaderSecSizeEncodingLen
);
665 // write reloc sections for any section that have relocations
666 uint32_t SectionIndex
= 0;
667 for (const std::unique_ptr
<WasmYAML::Section
> &Sec
: Obj
.Sections
) {
668 if (Sec
->Relocations
.empty()) {
673 writeUint8(OS
, wasm::WASM_SEC_CUSTOM
);
674 std::string OutString
;
675 raw_string_ostream
StringStream(OutString
);
676 writeRelocSection(StringStream
, *Sec
, SectionIndex
++);
677 StringStream
.flush();
679 encodeULEB128(OutString
.size(), OS
);
689 bool yaml2wasm(WasmYAML::Object
&Doc
, raw_ostream
&Out
, ErrorHandler EH
) {
690 WasmWriter
Writer(Doc
, EH
);
691 return Writer
.writeWasm(Out
);