blob: 9be2f09125aa337060a210559ed363053fcb44f0 [file] [log] [blame]
Derek Schuffd3d84fd2017-03-30 19:44:09 +00001//===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// \brief The Wasm component of yaml2obj.
12///
13//===----------------------------------------------------------------------===//
14//
Sam Clegg6c899ba2018-02-23 05:08:34 +000015
Derek Schuffd3d84fd2017-03-30 19:44:09 +000016#include "llvm/ObjectYAML/ObjectYAML.h"
17#include "llvm/Support/Endian.h"
18#include "llvm/Support/LEB128.h"
19
20using namespace llvm;
21
22/// This parses a yaml stream that represents a Wasm object file.
23/// See docs/yaml2obj for the yaml scheema.
24class WasmWriter {
25public:
26 WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
27 int writeWasm(raw_ostream &OS);
Sam Cleggb7787fd2017-06-20 04:04:59 +000028
29private:
Sam Clegg6f08c842018-04-24 18:11:36 +000030 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
31 uint32_t SectionIndex);
Sam Clegg03cdd122017-05-05 18:12:34 +000032
Derek Schuffd3d84fd2017-03-30 19:44:09 +000033 int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
34 int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
35 int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
36 int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
37 int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
38 int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
39 int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
40 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
41 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
42 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
43 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
44 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
45
Sam Cleggb7787fd2017-06-20 04:04:59 +000046 // Custom section types
47 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
48 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000049 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000050 uint32_t NumImportedFunctions = 0;
51 uint32_t NumImportedGlobals = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +000052};
53
54static int writeUint64(raw_ostream &OS, uint64_t Value) {
55 char Data[sizeof(Value)];
56 support::endian::write64le(Data, Value);
57 OS.write(Data, sizeof(Data));
58 return 0;
59}
60
61static int writeUint32(raw_ostream &OS, uint32_t Value) {
62 char Data[sizeof(Value)];
63 support::endian::write32le(Data, Value);
64 OS.write(Data, sizeof(Data));
65 return 0;
66}
67
68static int writeUint8(raw_ostream &OS, uint8_t Value) {
69 char Data[sizeof(Value)];
70 memcpy(Data, &Value, sizeof(Data));
71 OS.write(Data, sizeof(Data));
72 return 0;
73}
74
Sam Clegg03cdd122017-05-05 18:12:34 +000075static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000076 encodeULEB128(Str.size(), OS);
77 OS << Str;
78 return 0;
79}
80
Sam Clegg03cdd122017-05-05 18:12:34 +000081static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +000082 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000083 encodeULEB128(Lim.Initial, OS);
84 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
85 encodeULEB128(Lim.Maximum, OS);
86 return 0;
87}
88
Sam Clegg03cdd122017-05-05 18:12:34 +000089static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000090 writeUint8(OS, InitExpr.Opcode);
91 switch (InitExpr.Opcode) {
92 case wasm::WASM_OPCODE_I32_CONST:
93 encodeSLEB128(InitExpr.Value.Int32, OS);
94 break;
95 case wasm::WASM_OPCODE_I64_CONST:
96 encodeSLEB128(InitExpr.Value.Int64, OS);
97 break;
98 case wasm::WASM_OPCODE_F32_CONST:
99 writeUint32(OS, InitExpr.Value.Float32);
100 break;
101 case wasm::WASM_OPCODE_F64_CONST:
102 writeUint64(OS, InitExpr.Value.Float64);
103 break;
104 case wasm::WASM_OPCODE_GET_GLOBAL:
105 encodeULEB128(InitExpr.Value.Global, OS);
106 break;
107 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000108 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000109 return 1;
110 }
111 writeUint8(OS, wasm::WASM_OPCODE_END);
112 return 0;
113}
114
Sam Clegg9e1ade92017-06-27 20:27:59 +0000115class SubSectionWriter {
116 raw_ostream &OS;
117 std::string OutString;
118 raw_string_ostream StringStream;
Sam Cleggb7787fd2017-06-20 04:04:59 +0000119
Sam Clegg9e1ade92017-06-27 20:27:59 +0000120public:
121 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Cleggb7787fd2017-06-20 04:04:59 +0000122
Sam Clegg9e1ade92017-06-27 20:27:59 +0000123 void Done() {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000124 StringStream.flush();
125 encodeULEB128(OutString.size(), OS);
126 OS << OutString;
Sam Clegg9e1ade92017-06-27 20:27:59 +0000127 OutString.clear();
128 }
129
130 raw_ostream& GetStream() {
131 return StringStream;
132 }
133};
134
135int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
136 writeStringRef(Section.Name, OS);
Sam Clegg6bb5a412018-04-26 18:15:32 +0000137 encodeULEB128(Section.Version, OS);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000138
139 SubSectionWriter SubSection(OS);
140
Sam Clegg6c899ba2018-02-23 05:08:34 +0000141 // SYMBOL_TABLE subsection
142 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000143 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000144
Sam Clegg6c899ba2018-02-23 05:08:34 +0000145 encodeULEB128(Section.SymbolTable.size(), SubSection.GetStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000146#ifndef NDEBUG
Sam Clegg6c899ba2018-02-23 05:08:34 +0000147 uint32_t SymbolIndex = 0;
148#endif
149 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
150 assert(Info.Index == SymbolIndex++);
Sam Clegg03e101f2018-03-01 18:06:21 +0000151 writeUint8(SubSection.GetStream(), Info.Kind);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000152 encodeULEB128(Info.Flags, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000153 switch (Info.Kind) {
154 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
155 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
156 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
157 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
158 writeStringRef(Info.Name, SubSection.GetStream());
159 break;
160 case wasm::WASM_SYMBOL_TYPE_DATA:
161 writeStringRef(Info.Name, SubSection.GetStream());
162 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
163 encodeULEB128(Info.DataRef.Segment, SubSection.GetStream());
164 encodeULEB128(Info.DataRef.Offset, SubSection.GetStream());
165 encodeULEB128(Info.DataRef.Size, SubSection.GetStream());
166 }
167 break;
168 default:
169 llvm_unreachable("unexpected kind");
170 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000171 }
172
173 SubSection.Done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000174 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000175
176 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000177 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000178 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Sam Clegg63ebb812017-09-29 16:50:08 +0000179 encodeULEB128(Section.SegmentInfos.size(), SubSection.GetStream());
180 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Sam Clegg63ebb812017-09-29 16:50:08 +0000181 writeStringRef(SegmentInfo.Name, SubSection.GetStream());
182 encodeULEB128(SegmentInfo.Alignment, SubSection.GetStream());
183 encodeULEB128(SegmentInfo.Flags, SubSection.GetStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000184 }
185 SubSection.Done();
186 }
Sam Clegg42739982017-12-14 21:10:03 +0000187
188 // INIT_FUNCS subsection
189 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000190 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Sam Clegg42739982017-12-14 21:10:03 +0000191 encodeULEB128(Section.InitFunctions.size(), SubSection.GetStream());
192 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
193 encodeULEB128(Func.Priority, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000194 encodeULEB128(Func.Symbol, SubSection.GetStream());
Sam Clegg42739982017-12-14 21:10:03 +0000195 }
196 SubSection.Done();
197 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000198
199 // COMDAT_INFO subsection
200 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000201 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Sam Cleggea7cace2018-01-09 23:43:14 +0000202 encodeULEB128(Section.Comdats.size(), SubSection.GetStream());
203 for (const auto &C : Section.Comdats) {
204 writeStringRef(C.Name, SubSection.GetStream());
205 encodeULEB128(0, SubSection.GetStream()); // flags for future use
206 encodeULEB128(C.Entries.size(), SubSection.GetStream());
207 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000208 writeUint8(SubSection.GetStream(), Entry.Kind);
Sam Cleggea7cace2018-01-09 23:43:14 +0000209 encodeULEB128(Entry.Index, SubSection.GetStream());
210 }
211 }
212 SubSection.Done();
213 }
214
Sam Cleggb7787fd2017-06-20 04:04:59 +0000215 return 0;
216}
217
218int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000219 writeStringRef(Section.Name, OS);
220 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000221 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000222
Sam Clegg9e1ade92017-06-27 20:27:59 +0000223 SubSectionWriter SubSection(OS);
224
225 encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000226 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000227 encodeULEB128(NameEntry.Index, SubSection.GetStream());
228 writeStringRef(NameEntry.Name, SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000229 }
230
Sam Clegg9e1ade92017-06-27 20:27:59 +0000231 SubSection.Done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000232 }
233 return 0;
234}
235
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000236int WasmWriter::writeSectionContent(raw_ostream &OS,
237 WasmYAML::CustomSection &Section) {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000238 if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
239 if (auto Err = writeSectionContent(OS, *S))
240 return Err;
241 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
242 if (auto Err = writeSectionContent(OS, *S))
243 return Err;
Sam Clegg03cdd122017-05-05 18:12:34 +0000244 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000245 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000246 Section.Payload.writeAsBinary(OS);
247 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000248 return 0;
249}
250
251int WasmWriter::writeSectionContent(raw_ostream &OS,
252 WasmYAML::TypeSection &Section) {
253 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000254 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000255 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000256 if (Sig.Index != ExpectedIndex) {
257 errs() << "Unexpected type index: " << Sig.Index << "\n";
258 return 1;
259 }
260 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000261 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000262 encodeULEB128(Sig.ParamTypes.size(), OS);
263 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000264 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000265 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000266 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000267 } else {
268 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000269 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000270 }
271 }
272 return 0;
273}
274
275int WasmWriter::writeSectionContent(raw_ostream &OS,
276 WasmYAML::ImportSection &Section) {
277 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000278 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000279 writeStringRef(Import.Module, OS);
280 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000281 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000282 switch (Import.Kind) {
283 case wasm::WASM_EXTERNAL_FUNCTION:
284 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000285 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000286 break;
287 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000288 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000289 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000290 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000291 break;
292 case wasm::WASM_EXTERNAL_MEMORY:
293 writeLimits(Import.Memory, OS);
294 break;
295 case wasm::WASM_EXTERNAL_TABLE:
Sam Clegg03e101f2018-03-01 18:06:21 +0000296 writeUint8(OS,Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000297 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000298 break;
299 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000300 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000301 return 1;
302 }
303 }
304 return 0;
305}
306
307int WasmWriter::writeSectionContent(raw_ostream &OS,
308 WasmYAML::FunctionSection &Section) {
309 encodeULEB128(Section.FunctionTypes.size(), OS);
310 for (uint32_t FuncType : Section.FunctionTypes) {
311 encodeULEB128(FuncType, OS);
312 }
313 return 0;
314}
315
316int WasmWriter::writeSectionContent(raw_ostream &OS,
317 WasmYAML::ExportSection &Section) {
318 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000319 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000320 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000321 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000322 encodeULEB128(Export.Index, OS);
323 }
324 return 0;
325}
326
327int WasmWriter::writeSectionContent(raw_ostream &OS,
328 WasmYAML::StartSection &Section) {
329 encodeULEB128(Section.StartFunction, OS);
330 return 0;
331}
332
333int WasmWriter::writeSectionContent(raw_ostream &OS,
334 WasmYAML::TableSection &Section) {
335 encodeULEB128(Section.Tables.size(), OS);
336 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000337 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000338 writeLimits(Table.TableLimits, OS);
339 }
340 return 0;
341}
342
343int WasmWriter::writeSectionContent(raw_ostream &OS,
344 WasmYAML::MemorySection &Section) {
345 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000346 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000347 writeLimits(Mem, OS);
348 }
349 return 0;
350}
351
352int WasmWriter::writeSectionContent(raw_ostream &OS,
353 WasmYAML::GlobalSection &Section) {
354 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000355 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000356 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000357 if (Global.Index != ExpectedIndex) {
358 errs() << "Unexpected global index: " << Global.Index << "\n";
359 return 1;
360 }
361 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000362 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000363 writeUint8(OS, Global.Mutable);
364 writeInitExpr(Global.InitExpr, OS);
365 }
366 return 0;
367}
368
369int WasmWriter::writeSectionContent(raw_ostream &OS,
370 WasmYAML::ElemSection &Section) {
371 encodeULEB128(Section.Segments.size(), OS);
372 for (auto &Segment : Section.Segments) {
373 encodeULEB128(Segment.TableIndex, OS);
374 writeInitExpr(Segment.Offset, OS);
375
376 encodeULEB128(Segment.Functions.size(), OS);
377 for (auto &Function : Segment.Functions) {
378 encodeULEB128(Function, OS);
379 }
380 }
381 return 0;
382}
383
384int WasmWriter::writeSectionContent(raw_ostream &OS,
385 WasmYAML::CodeSection &Section) {
386 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000387 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000388 for (auto &Func : Section.Functions) {
389 std::string OutString;
390 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000391 if (Func.Index != ExpectedIndex) {
392 errs() << "Unexpected function index: " << Func.Index << "\n";
393 return 1;
394 }
395 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000396
397 encodeULEB128(Func.Locals.size(), StringStream);
398 for (auto &LocalDecl : Func.Locals) {
399 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000400 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000401 }
402
403 Func.Body.writeAsBinary(StringStream);
404
405 // Write the section size followed by the content
406 StringStream.flush();
407 encodeULEB128(OutString.size(), OS);
408 OS << OutString;
409 }
410 return 0;
411}
412
413int WasmWriter::writeSectionContent(raw_ostream &OS,
414 WasmYAML::DataSection &Section) {
415 encodeULEB128(Section.Segments.size(), OS);
416 for (auto &Segment : Section.Segments) {
Sam Clegg9c07f942017-07-12 00:24:54 +0000417 encodeULEB128(Segment.MemoryIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000418 writeInitExpr(Segment.Offset, OS);
419 encodeULEB128(Segment.Content.binary_size(), OS);
420 Segment.Content.writeAsBinary(OS);
421 }
422 return 0;
423}
424
Sam Clegg6f08c842018-04-24 18:11:36 +0000425int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
426 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000427 StringRef Name;
428 switch (Sec.Type) {
429 case wasm::WASM_SEC_CODE:
430 Name = "reloc.CODE";
431 break;
432 case wasm::WASM_SEC_DATA:
433 Name = "reloc.DATA";
434 break;
435 default:
436 llvm_unreachable("not yet implemented");
437 return 1;
438 }
439
440 writeStringRef(Name, OS);
Sam Clegg6f08c842018-04-24 18:11:36 +0000441 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000442 encodeULEB128(Sec.Relocations.size(), OS);
443
444 for (auto Reloc: Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000445 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000446 encodeULEB128(Reloc.Offset, OS);
447 encodeULEB128(Reloc.Index, OS);
448 switch (Reloc.Type) {
Sam Clegg13a2e892017-09-01 17:32:01 +0000449 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
450 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
451 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000452 encodeULEB128(Reloc.Addend, OS);
453 }
454 }
455 return 0;
456}
457
458
459int WasmWriter::writeWasm(raw_ostream &OS) {
460 // Write headers
461 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
462 writeUint32(OS, Obj.Header.Version);
463
464 // Write each section
Sam Clegge53af7f2018-01-09 21:38:53 +0000465 uint32_t LastType = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000466 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000467 uint32_t Type = Sec->Type;
468 if (Type != wasm::WASM_SEC_CUSTOM) {
469 if (Type < LastType) {
470 errs() << "Out of order section type: " << Type << "\n";
471 return 1;
472 }
473 LastType = Type;
474 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000475
Sam Clegge53af7f2018-01-09 21:38:53 +0000476 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000477 std::string OutString;
478 raw_string_ostream StringStream(OutString);
479 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
480 if (auto Err = writeSectionContent(StringStream, *S))
481 return Err;
482 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
483 if (auto Err = writeSectionContent(StringStream, *S))
484 return Err;
485 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
486 if (auto Err = writeSectionContent(StringStream, *S))
487 return Err;
488 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
489 if (auto Err = writeSectionContent(StringStream, *S))
490 return Err;
491 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
492 if (auto Err = writeSectionContent(StringStream, *S))
493 return Err;
494 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
495 if (auto Err = writeSectionContent(StringStream, *S))
496 return Err;
497 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
498 if (auto Err = writeSectionContent(StringStream, *S))
499 return Err;
500 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
501 if (auto Err = writeSectionContent(StringStream, *S))
502 return Err;
503 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
504 if (auto Err = writeSectionContent(StringStream, *S))
505 return Err;
506 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
507 if (auto Err = writeSectionContent(StringStream, *S))
508 return Err;
509 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
510 if (auto Err = writeSectionContent(StringStream, *S))
511 return Err;
512 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
513 if (auto Err = writeSectionContent(StringStream, *S))
514 return Err;
515 } else {
516 errs() << "Unknown section type: " << Sec->Type << "\n";
517 return 1;
518 }
519 StringStream.flush();
520
521 // Write the section size followed by the content
522 encodeULEB128(OutString.size(), OS);
523 OS << OutString;
524 }
525
526 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000527 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000528 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000529 if (Sec->Relocations.empty()) {
530 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000531 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000532 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000533
Sam Clegg03e101f2018-03-01 18:06:21 +0000534 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000535 std::string OutString;
536 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000537 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000538 StringStream.flush();
539
540 encodeULEB128(OutString.size(), OS);
541 OS << OutString;
542 }
543
544 return 0;
545}
546
547int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
548 WasmWriter Writer(Doc);
549
550 return Writer.writeWasm(Out);
551}