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 wasm::WasmInitExpr
&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 wasm::WasmInitExpr
&InitExpr
) {
133 writeUint8(OS
, InitExpr
.Opcode
);
134 switch (InitExpr
.Opcode
) {
135 case wasm::WASM_OPCODE_I32_CONST
:
136 encodeSLEB128(InitExpr
.Value
.Int32
, OS
);
138 case wasm::WASM_OPCODE_I64_CONST
:
139 encodeSLEB128(InitExpr
.Value
.Int64
, OS
);
141 case wasm::WASM_OPCODE_F32_CONST
:
142 writeUint32(OS
, InitExpr
.Value
.Float32
);
144 case wasm::WASM_OPCODE_F64_CONST
:
145 writeUint64(OS
, InitExpr
.Value
.Float64
);
147 case wasm::WASM_OPCODE_GLOBAL_GET
:
148 encodeULEB128(InitExpr
.Value
.Global
, OS
);
151 reportError("unknown opcode in init_expr: " + Twine(InitExpr
.Opcode
));
154 writeUint8(OS
, wasm::WASM_OPCODE_END
);
157 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
158 WasmYAML::DylinkSection
&Section
) {
159 writeStringRef(Section
.Name
, OS
);
160 encodeULEB128(Section
.MemorySize
, OS
);
161 encodeULEB128(Section
.MemoryAlignment
, OS
);
162 encodeULEB128(Section
.TableSize
, OS
);
163 encodeULEB128(Section
.TableAlignment
, OS
);
164 encodeULEB128(Section
.Needed
.size(), OS
);
165 for (StringRef Needed
: Section
.Needed
)
166 writeStringRef(Needed
, OS
);
169 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
170 WasmYAML::LinkingSection
&Section
) {
171 writeStringRef(Section
.Name
, OS
);
172 encodeULEB128(Section
.Version
, OS
);
174 SubSectionWriter
SubSection(OS
);
176 // SYMBOL_TABLE subsection
177 if (Section
.SymbolTable
.size()) {
178 writeUint8(OS
, wasm::WASM_SYMBOL_TABLE
);
180 encodeULEB128(Section
.SymbolTable
.size(), SubSection
.getStream());
182 uint32_t SymbolIndex
= 0;
184 for (const WasmYAML::SymbolInfo
&Info
: Section
.SymbolTable
) {
185 assert(Info
.Index
== SymbolIndex
++);
186 writeUint8(SubSection
.getStream(), Info
.Kind
);
187 encodeULEB128(Info
.Flags
, SubSection
.getStream());
189 case wasm::WASM_SYMBOL_TYPE_FUNCTION
:
190 case wasm::WASM_SYMBOL_TYPE_GLOBAL
:
191 case wasm::WASM_SYMBOL_TYPE_TABLE
:
192 case wasm::WASM_SYMBOL_TYPE_TAG
:
193 encodeULEB128(Info
.ElementIndex
, SubSection
.getStream());
194 if ((Info
.Flags
& wasm::WASM_SYMBOL_UNDEFINED
) == 0 ||
195 (Info
.Flags
& wasm::WASM_SYMBOL_EXPLICIT_NAME
) != 0)
196 writeStringRef(Info
.Name
, SubSection
.getStream());
198 case wasm::WASM_SYMBOL_TYPE_DATA
:
199 writeStringRef(Info
.Name
, SubSection
.getStream());
200 if ((Info
.Flags
& wasm::WASM_SYMBOL_UNDEFINED
) == 0) {
201 encodeULEB128(Info
.DataRef
.Segment
, SubSection
.getStream());
202 encodeULEB128(Info
.DataRef
.Offset
, SubSection
.getStream());
203 encodeULEB128(Info
.DataRef
.Size
, SubSection
.getStream());
206 case wasm::WASM_SYMBOL_TYPE_SECTION
:
207 encodeULEB128(Info
.ElementIndex
, SubSection
.getStream());
210 llvm_unreachable("unexpected kind");
217 // SEGMENT_NAMES subsection
218 if (Section
.SegmentInfos
.size()) {
219 writeUint8(OS
, wasm::WASM_SEGMENT_INFO
);
220 encodeULEB128(Section
.SegmentInfos
.size(), SubSection
.getStream());
221 for (const WasmYAML::SegmentInfo
&SegmentInfo
: Section
.SegmentInfos
) {
222 writeStringRef(SegmentInfo
.Name
, SubSection
.getStream());
223 encodeULEB128(SegmentInfo
.Alignment
, SubSection
.getStream());
224 encodeULEB128(SegmentInfo
.Flags
, SubSection
.getStream());
229 // INIT_FUNCS subsection
230 if (Section
.InitFunctions
.size()) {
231 writeUint8(OS
, wasm::WASM_INIT_FUNCS
);
232 encodeULEB128(Section
.InitFunctions
.size(), SubSection
.getStream());
233 for (const WasmYAML::InitFunction
&Func
: Section
.InitFunctions
) {
234 encodeULEB128(Func
.Priority
, SubSection
.getStream());
235 encodeULEB128(Func
.Symbol
, SubSection
.getStream());
240 // COMDAT_INFO subsection
241 if (Section
.Comdats
.size()) {
242 writeUint8(OS
, wasm::WASM_COMDAT_INFO
);
243 encodeULEB128(Section
.Comdats
.size(), SubSection
.getStream());
244 for (const auto &C
: Section
.Comdats
) {
245 writeStringRef(C
.Name
, SubSection
.getStream());
246 encodeULEB128(0, SubSection
.getStream()); // flags for future use
247 encodeULEB128(C
.Entries
.size(), SubSection
.getStream());
248 for (const WasmYAML::ComdatEntry
&Entry
: C
.Entries
) {
249 writeUint8(SubSection
.getStream(), Entry
.Kind
);
250 encodeULEB128(Entry
.Index
, SubSection
.getStream());
257 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
258 WasmYAML::NameSection
&Section
) {
259 writeStringRef(Section
.Name
, OS
);
260 if (Section
.FunctionNames
.size()) {
261 writeUint8(OS
, wasm::WASM_NAMES_FUNCTION
);
263 SubSectionWriter
SubSection(OS
);
265 encodeULEB128(Section
.FunctionNames
.size(), SubSection
.getStream());
266 for (const WasmYAML::NameEntry
&NameEntry
: Section
.FunctionNames
) {
267 encodeULEB128(NameEntry
.Index
, SubSection
.getStream());
268 writeStringRef(NameEntry
.Name
, SubSection
.getStream());
273 if (Section
.GlobalNames
.size()) {
274 writeUint8(OS
, wasm::WASM_NAMES_GLOBAL
);
276 SubSectionWriter
SubSection(OS
);
278 encodeULEB128(Section
.GlobalNames
.size(), SubSection
.getStream());
279 for (const WasmYAML::NameEntry
&NameEntry
: Section
.GlobalNames
) {
280 encodeULEB128(NameEntry
.Index
, SubSection
.getStream());
281 writeStringRef(NameEntry
.Name
, SubSection
.getStream());
286 if (Section
.DataSegmentNames
.size()) {
287 writeUint8(OS
, wasm::WASM_NAMES_DATA_SEGMENT
);
289 SubSectionWriter
SubSection(OS
);
291 encodeULEB128(Section
.DataSegmentNames
.size(), SubSection
.getStream());
292 for (const WasmYAML::NameEntry
&NameEntry
: Section
.DataSegmentNames
) {
293 encodeULEB128(NameEntry
.Index
, SubSection
.getStream());
294 writeStringRef(NameEntry
.Name
, SubSection
.getStream());
301 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
302 WasmYAML::ProducersSection
&Section
) {
303 writeStringRef(Section
.Name
, OS
);
304 int Fields
= int(!Section
.Languages
.empty()) + int(!Section
.Tools
.empty()) +
305 int(!Section
.SDKs
.empty());
308 encodeULEB128(Fields
, OS
);
309 for (auto &Field
: {std::make_pair(StringRef("language"), &Section
.Languages
),
310 std::make_pair(StringRef("processed-by"), &Section
.Tools
),
311 std::make_pair(StringRef("sdk"), &Section
.SDKs
)}) {
312 if (Field
.second
->empty())
314 writeStringRef(Field
.first
, OS
);
315 encodeULEB128(Field
.second
->size(), OS
);
316 for (auto &Entry
: *Field
.second
) {
317 writeStringRef(Entry
.Name
, OS
);
318 writeStringRef(Entry
.Version
, OS
);
323 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
324 WasmYAML::TargetFeaturesSection
&Section
) {
325 writeStringRef(Section
.Name
, OS
);
326 encodeULEB128(Section
.Features
.size(), OS
);
327 for (auto &E
: Section
.Features
) {
328 writeUint8(OS
, E
.Prefix
);
329 writeStringRef(E
.Name
, OS
);
333 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
334 WasmYAML::CustomSection
&Section
) {
335 if (auto S
= dyn_cast
<WasmYAML::DylinkSection
>(&Section
)) {
336 writeSectionContent(OS
, *S
);
337 } else if (auto S
= dyn_cast
<WasmYAML::NameSection
>(&Section
)) {
338 writeSectionContent(OS
, *S
);
339 } else if (auto S
= dyn_cast
<WasmYAML::LinkingSection
>(&Section
)) {
340 writeSectionContent(OS
, *S
);
341 } else if (auto S
= dyn_cast
<WasmYAML::ProducersSection
>(&Section
)) {
342 writeSectionContent(OS
, *S
);
343 } else if (auto S
= dyn_cast
<WasmYAML::TargetFeaturesSection
>(&Section
)) {
344 writeSectionContent(OS
, *S
);
346 writeStringRef(Section
.Name
, OS
);
347 Section
.Payload
.writeAsBinary(OS
);
351 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
352 WasmYAML::TypeSection
&Section
) {
353 encodeULEB128(Section
.Signatures
.size(), OS
);
354 uint32_t ExpectedIndex
= 0;
355 for (const WasmYAML::Signature
&Sig
: Section
.Signatures
) {
356 if (Sig
.Index
!= ExpectedIndex
) {
357 reportError("unexpected type index: " + Twine(Sig
.Index
));
361 writeUint8(OS
, Sig
.Form
);
362 encodeULEB128(Sig
.ParamTypes
.size(), OS
);
363 for (auto ParamType
: Sig
.ParamTypes
)
364 writeUint8(OS
, ParamType
);
365 encodeULEB128(Sig
.ReturnTypes
.size(), OS
);
366 for (auto ReturnType
: Sig
.ReturnTypes
)
367 writeUint8(OS
, ReturnType
);
371 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
372 WasmYAML::ImportSection
&Section
) {
373 encodeULEB128(Section
.Imports
.size(), OS
);
374 for (const WasmYAML::Import
&Import
: Section
.Imports
) {
375 writeStringRef(Import
.Module
, OS
);
376 writeStringRef(Import
.Field
, OS
);
377 writeUint8(OS
, Import
.Kind
);
378 switch (Import
.Kind
) {
379 case wasm::WASM_EXTERNAL_FUNCTION
:
380 encodeULEB128(Import
.SigIndex
, OS
);
381 NumImportedFunctions
++;
383 case wasm::WASM_EXTERNAL_GLOBAL
:
384 writeUint8(OS
, Import
.GlobalImport
.Type
);
385 writeUint8(OS
, Import
.GlobalImport
.Mutable
);
386 NumImportedGlobals
++;
388 case wasm::WASM_EXTERNAL_TAG
:
389 writeUint32(OS
, Import
.TagImport
.Attribute
);
390 writeUint32(OS
, Import
.TagImport
.SigIndex
);
393 case wasm::WASM_EXTERNAL_MEMORY
:
394 writeLimits(Import
.Memory
, OS
);
396 case wasm::WASM_EXTERNAL_TABLE
:
397 writeUint8(OS
, Import
.TableImport
.ElemType
);
398 writeLimits(Import
.TableImport
.TableLimits
, OS
);
402 reportError("unknown import type: " +Twine(Import
.Kind
));
408 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
409 WasmYAML::FunctionSection
&Section
) {
410 encodeULEB128(Section
.FunctionTypes
.size(), OS
);
411 for (uint32_t FuncType
: Section
.FunctionTypes
)
412 encodeULEB128(FuncType
, OS
);
415 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
416 WasmYAML::ExportSection
&Section
) {
417 encodeULEB128(Section
.Exports
.size(), OS
);
418 for (const WasmYAML::Export
&Export
: Section
.Exports
) {
419 writeStringRef(Export
.Name
, OS
);
420 writeUint8(OS
, Export
.Kind
);
421 encodeULEB128(Export
.Index
, OS
);
425 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
426 WasmYAML::StartSection
&Section
) {
427 encodeULEB128(Section
.StartFunction
, OS
);
430 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
431 WasmYAML::TableSection
&Section
) {
432 encodeULEB128(Section
.Tables
.size(), OS
);
433 uint32_t ExpectedIndex
= NumImportedTables
;
434 for (auto &Table
: Section
.Tables
) {
435 if (Table
.Index
!= ExpectedIndex
) {
436 reportError("unexpected table index: " + Twine(Table
.Index
));
440 writeUint8(OS
, Table
.ElemType
);
441 writeLimits(Table
.TableLimits
, OS
);
445 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
446 WasmYAML::MemorySection
&Section
) {
447 encodeULEB128(Section
.Memories
.size(), OS
);
448 for (const WasmYAML::Limits
&Mem
: Section
.Memories
)
449 writeLimits(Mem
, OS
);
452 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
453 WasmYAML::TagSection
&Section
) {
454 encodeULEB128(Section
.Tags
.size(), OS
);
455 uint32_t ExpectedIndex
= NumImportedTags
;
456 for (auto &Tag
: Section
.Tags
) {
457 if (Tag
.Index
!= ExpectedIndex
) {
458 reportError("unexpected tag index: " + Twine(Tag
.Index
));
462 encodeULEB128(Tag
.Attribute
, OS
);
463 encodeULEB128(Tag
.SigIndex
, OS
);
467 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
468 WasmYAML::GlobalSection
&Section
) {
469 encodeULEB128(Section
.Globals
.size(), OS
);
470 uint32_t ExpectedIndex
= NumImportedGlobals
;
471 for (auto &Global
: Section
.Globals
) {
472 if (Global
.Index
!= ExpectedIndex
) {
473 reportError("unexpected global index: " + Twine(Global
.Index
));
477 writeUint8(OS
, Global
.Type
);
478 writeUint8(OS
, Global
.Mutable
);
479 writeInitExpr(OS
, Global
.InitExpr
);
483 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
484 WasmYAML::ElemSection
&Section
) {
485 encodeULEB128(Section
.Segments
.size(), OS
);
486 for (auto &Segment
: Section
.Segments
) {
487 encodeULEB128(Segment
.Flags
, OS
);
488 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
)
489 encodeULEB128(Segment
.TableNumber
, OS
);
491 writeInitExpr(OS
, Segment
.Offset
);
493 if (Segment
.Flags
& wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
) {
494 // We only support active function table initializers, for which the elem
495 // kind is specified to be written as 0x00 and interpreted to mean
497 if (Segment
.ElemKind
!= uint32_t(wasm::ValType::FUNCREF
)) {
498 reportError("unexpected elemkind: " + Twine(Segment
.ElemKind
));
501 const uint8_t ElemKind
= 0;
502 writeUint8(OS
, ElemKind
);
505 encodeULEB128(Segment
.Functions
.size(), OS
);
506 for (auto &Function
: Segment
.Functions
)
507 encodeULEB128(Function
, OS
);
511 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
512 WasmYAML::CodeSection
&Section
) {
513 encodeULEB128(Section
.Functions
.size(), OS
);
514 uint32_t ExpectedIndex
= NumImportedFunctions
;
515 for (auto &Func
: Section
.Functions
) {
516 std::string OutString
;
517 raw_string_ostream
StringStream(OutString
);
518 if (Func
.Index
!= ExpectedIndex
) {
519 reportError("unexpected function index: " + Twine(Func
.Index
));
524 encodeULEB128(Func
.Locals
.size(), StringStream
);
525 for (auto &LocalDecl
: Func
.Locals
) {
526 encodeULEB128(LocalDecl
.Count
, StringStream
);
527 writeUint8(StringStream
, LocalDecl
.Type
);
530 Func
.Body
.writeAsBinary(StringStream
);
532 // Write the section size followed by the content
533 StringStream
.flush();
534 encodeULEB128(OutString
.size(), OS
);
539 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
540 WasmYAML::DataSection
&Section
) {
541 encodeULEB128(Section
.Segments
.size(), OS
);
542 for (auto &Segment
: Section
.Segments
) {
543 encodeULEB128(Segment
.InitFlags
, OS
);
544 if (Segment
.InitFlags
& wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX
)
545 encodeULEB128(Segment
.MemoryIndex
, OS
);
546 if ((Segment
.InitFlags
& wasm::WASM_DATA_SEGMENT_IS_PASSIVE
) == 0)
547 writeInitExpr(OS
, Segment
.Offset
);
548 encodeULEB128(Segment
.Content
.binary_size(), OS
);
549 Segment
.Content
.writeAsBinary(OS
);
553 void WasmWriter::writeSectionContent(raw_ostream
&OS
,
554 WasmYAML::DataCountSection
&Section
) {
555 encodeULEB128(Section
.Count
, OS
);
558 void WasmWriter::writeRelocSection(raw_ostream
&OS
, WasmYAML::Section
&Sec
,
559 uint32_t SectionIndex
) {
561 case wasm::WASM_SEC_CODE
:
562 writeStringRef("reloc.CODE", OS
);
564 case wasm::WASM_SEC_DATA
:
565 writeStringRef("reloc.DATA", OS
);
567 case wasm::WASM_SEC_CUSTOM
: {
568 auto *CustomSection
= cast
<WasmYAML::CustomSection
>(&Sec
);
569 writeStringRef(("reloc." + CustomSection
->Name
).str(), OS
);
573 llvm_unreachable("not yet implemented");
576 encodeULEB128(SectionIndex
, OS
);
577 encodeULEB128(Sec
.Relocations
.size(), OS
);
579 for (auto Reloc
: Sec
.Relocations
) {
580 writeUint8(OS
, Reloc
.Type
);
581 encodeULEB128(Reloc
.Offset
, OS
);
582 encodeULEB128(Reloc
.Index
, OS
);
583 switch (Reloc
.Type
) {
584 case wasm::R_WASM_MEMORY_ADDR_LEB
:
585 case wasm::R_WASM_MEMORY_ADDR_LEB64
:
586 case wasm::R_WASM_MEMORY_ADDR_SLEB
:
587 case wasm::R_WASM_MEMORY_ADDR_SLEB64
:
588 case wasm::R_WASM_MEMORY_ADDR_I32
:
589 case wasm::R_WASM_MEMORY_ADDR_I64
:
590 case wasm::R_WASM_FUNCTION_OFFSET_I32
:
591 case wasm::R_WASM_FUNCTION_OFFSET_I64
:
592 case wasm::R_WASM_SECTION_OFFSET_I32
:
593 encodeSLEB128(Reloc
.Addend
, OS
);
599 bool WasmWriter::writeWasm(raw_ostream
&OS
) {
601 OS
.write(wasm::WasmMagic
, sizeof(wasm::WasmMagic
));
602 writeUint32(OS
, Obj
.Header
.Version
);
604 // Write each section
605 llvm::object::WasmSectionOrderChecker Checker
;
606 for (const std::unique_ptr
<WasmYAML::Section
> &Sec
: Obj
.Sections
) {
607 StringRef SecName
= "";
608 if (auto S
= dyn_cast
<WasmYAML::CustomSection
>(Sec
.get()))
610 if (!Checker
.isValidSectionOrder(Sec
->Type
, SecName
)) {
611 reportError("out of order section type: " + Twine(Sec
->Type
));
614 encodeULEB128(Sec
->Type
, OS
);
615 std::string OutString
;
616 raw_string_ostream
StringStream(OutString
);
617 if (auto S
= dyn_cast
<WasmYAML::CustomSection
>(Sec
.get()))
618 writeSectionContent(StringStream
, *S
);
619 else if (auto S
= dyn_cast
<WasmYAML::TypeSection
>(Sec
.get()))
620 writeSectionContent(StringStream
, *S
);
621 else if (auto S
= dyn_cast
<WasmYAML::ImportSection
>(Sec
.get()))
622 writeSectionContent(StringStream
, *S
);
623 else if (auto S
= dyn_cast
<WasmYAML::FunctionSection
>(Sec
.get()))
624 writeSectionContent(StringStream
, *S
);
625 else if (auto S
= dyn_cast
<WasmYAML::TableSection
>(Sec
.get()))
626 writeSectionContent(StringStream
, *S
);
627 else if (auto S
= dyn_cast
<WasmYAML::MemorySection
>(Sec
.get()))
628 writeSectionContent(StringStream
, *S
);
629 else if (auto S
= dyn_cast
<WasmYAML::TagSection
>(Sec
.get()))
630 writeSectionContent(StringStream
, *S
);
631 else if (auto S
= dyn_cast
<WasmYAML::GlobalSection
>(Sec
.get()))
632 writeSectionContent(StringStream
, *S
);
633 else if (auto S
= dyn_cast
<WasmYAML::ExportSection
>(Sec
.get()))
634 writeSectionContent(StringStream
, *S
);
635 else if (auto S
= dyn_cast
<WasmYAML::StartSection
>(Sec
.get()))
636 writeSectionContent(StringStream
, *S
);
637 else if (auto S
= dyn_cast
<WasmYAML::ElemSection
>(Sec
.get()))
638 writeSectionContent(StringStream
, *S
);
639 else if (auto S
= dyn_cast
<WasmYAML::CodeSection
>(Sec
.get()))
640 writeSectionContent(StringStream
, *S
);
641 else if (auto S
= dyn_cast
<WasmYAML::DataSection
>(Sec
.get()))
642 writeSectionContent(StringStream
, *S
);
643 else if (auto S
= dyn_cast
<WasmYAML::DataCountSection
>(Sec
.get()))
644 writeSectionContent(StringStream
, *S
);
646 reportError("unknown section type: " + Twine(Sec
->Type
));
651 StringStream
.flush();
653 // Write the section size followed by the content
654 encodeULEB128(OutString
.size(), OS
);
658 // write reloc sections for any section that have relocations
659 uint32_t SectionIndex
= 0;
660 for (const std::unique_ptr
<WasmYAML::Section
> &Sec
: Obj
.Sections
) {
661 if (Sec
->Relocations
.empty()) {
666 writeUint8(OS
, wasm::WASM_SEC_CUSTOM
);
667 std::string OutString
;
668 raw_string_ostream
StringStream(OutString
);
669 writeRelocSection(StringStream
, *Sec
, SectionIndex
++);
670 StringStream
.flush();
672 encodeULEB128(OutString
.size(), OS
);
682 bool yaml2wasm(WasmYAML::Object
&Doc
, raw_ostream
&Out
, ErrorHandler EH
) {
683 WasmWriter
Writer(Doc
, EH
);
684 return Writer
.writeWasm(Out
);