blob: ab1659905ab4e97948ff522496e00251fe523b7d [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:
Derek Schuffd3d84fd2017-03-30 19:44:09 +000030 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec);
Sam Clegg03cdd122017-05-05 18:12:34 +000031
Derek Schuffd3d84fd2017-03-30 19:44:09 +000032 int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
33 int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
34 int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
35 int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
36 int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
37 int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
38 int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
39 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
40 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
41 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
42 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
43 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
44
Sam Cleggb7787fd2017-06-20 04:04:59 +000045 // Custom section types
46 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
47 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000048 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000049 uint32_t NumImportedFunctions = 0;
50 uint32_t NumImportedGlobals = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +000051};
52
53static int writeUint64(raw_ostream &OS, uint64_t Value) {
54 char Data[sizeof(Value)];
55 support::endian::write64le(Data, Value);
56 OS.write(Data, sizeof(Data));
57 return 0;
58}
59
60static int writeUint32(raw_ostream &OS, uint32_t Value) {
61 char Data[sizeof(Value)];
62 support::endian::write32le(Data, Value);
63 OS.write(Data, sizeof(Data));
64 return 0;
65}
66
67static int writeUint8(raw_ostream &OS, uint8_t Value) {
68 char Data[sizeof(Value)];
69 memcpy(Data, &Value, sizeof(Data));
70 OS.write(Data, sizeof(Data));
71 return 0;
72}
73
Sam Clegg03cdd122017-05-05 18:12:34 +000074static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000075 encodeULEB128(Str.size(), OS);
76 OS << Str;
77 return 0;
78}
79
Sam Clegg03cdd122017-05-05 18:12:34 +000080static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +000081 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000082 encodeULEB128(Lim.Initial, OS);
83 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
84 encodeULEB128(Lim.Maximum, OS);
85 return 0;
86}
87
Sam Clegg03cdd122017-05-05 18:12:34 +000088static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000089 writeUint8(OS, InitExpr.Opcode);
90 switch (InitExpr.Opcode) {
91 case wasm::WASM_OPCODE_I32_CONST:
92 encodeSLEB128(InitExpr.Value.Int32, OS);
93 break;
94 case wasm::WASM_OPCODE_I64_CONST:
95 encodeSLEB128(InitExpr.Value.Int64, OS);
96 break;
97 case wasm::WASM_OPCODE_F32_CONST:
98 writeUint32(OS, InitExpr.Value.Float32);
99 break;
100 case wasm::WASM_OPCODE_F64_CONST:
101 writeUint64(OS, InitExpr.Value.Float64);
102 break;
103 case wasm::WASM_OPCODE_GET_GLOBAL:
104 encodeULEB128(InitExpr.Value.Global, OS);
105 break;
106 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000107 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000108 return 1;
109 }
110 writeUint8(OS, wasm::WASM_OPCODE_END);
111 return 0;
112}
113
Sam Clegg9e1ade92017-06-27 20:27:59 +0000114class SubSectionWriter {
115 raw_ostream &OS;
116 std::string OutString;
117 raw_string_ostream StringStream;
Sam Cleggb7787fd2017-06-20 04:04:59 +0000118
Sam Clegg9e1ade92017-06-27 20:27:59 +0000119public:
120 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Cleggb7787fd2017-06-20 04:04:59 +0000121
Sam Clegg9e1ade92017-06-27 20:27:59 +0000122 void Done() {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000123 StringStream.flush();
124 encodeULEB128(OutString.size(), OS);
125 OS << OutString;
Sam Clegg9e1ade92017-06-27 20:27:59 +0000126 OutString.clear();
127 }
128
129 raw_ostream& GetStream() {
130 return StringStream;
131 }
132};
133
134int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
135 writeStringRef(Section.Name, OS);
136
137 SubSectionWriter SubSection(OS);
138
Sam Clegg6c899ba2018-02-23 05:08:34 +0000139 // SYMBOL_TABLE subsection
140 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000141 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000142
Sam Clegg6c899ba2018-02-23 05:08:34 +0000143 encodeULEB128(Section.SymbolTable.size(), SubSection.GetStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000144#ifndef NDEBUG
Sam Clegg6c899ba2018-02-23 05:08:34 +0000145 uint32_t SymbolIndex = 0;
146#endif
147 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
148 assert(Info.Index == SymbolIndex++);
Sam Clegg03e101f2018-03-01 18:06:21 +0000149 writeUint8(SubSection.GetStream(), Info.Kind);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000150 encodeULEB128(Info.Flags, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000151 switch (Info.Kind) {
152 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
153 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
154 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
155 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
156 writeStringRef(Info.Name, SubSection.GetStream());
157 break;
158 case wasm::WASM_SYMBOL_TYPE_DATA:
159 writeStringRef(Info.Name, SubSection.GetStream());
160 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
161 encodeULEB128(Info.DataRef.Segment, SubSection.GetStream());
162 encodeULEB128(Info.DataRef.Offset, SubSection.GetStream());
163 encodeULEB128(Info.DataRef.Size, SubSection.GetStream());
164 }
165 break;
166 default:
167 llvm_unreachable("unexpected kind");
168 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000169 }
170
171 SubSection.Done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000172 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000173
174 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000175 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000176 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Sam Clegg63ebb812017-09-29 16:50:08 +0000177 encodeULEB128(Section.SegmentInfos.size(), SubSection.GetStream());
178 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Sam Clegg63ebb812017-09-29 16:50:08 +0000179 writeStringRef(SegmentInfo.Name, SubSection.GetStream());
180 encodeULEB128(SegmentInfo.Alignment, SubSection.GetStream());
181 encodeULEB128(SegmentInfo.Flags, SubSection.GetStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000182 }
183 SubSection.Done();
184 }
Sam Clegg42739982017-12-14 21:10:03 +0000185
186 // INIT_FUNCS subsection
187 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000188 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Sam Clegg42739982017-12-14 21:10:03 +0000189 encodeULEB128(Section.InitFunctions.size(), SubSection.GetStream());
190 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
191 encodeULEB128(Func.Priority, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000192 encodeULEB128(Func.Symbol, SubSection.GetStream());
Sam Clegg42739982017-12-14 21:10:03 +0000193 }
194 SubSection.Done();
195 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000196
197 // COMDAT_INFO subsection
198 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000199 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Sam Cleggea7cace2018-01-09 23:43:14 +0000200 encodeULEB128(Section.Comdats.size(), SubSection.GetStream());
201 for (const auto &C : Section.Comdats) {
202 writeStringRef(C.Name, SubSection.GetStream());
203 encodeULEB128(0, SubSection.GetStream()); // flags for future use
204 encodeULEB128(C.Entries.size(), SubSection.GetStream());
205 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000206 writeUint8(SubSection.GetStream(), Entry.Kind);
Sam Cleggea7cace2018-01-09 23:43:14 +0000207 encodeULEB128(Entry.Index, SubSection.GetStream());
208 }
209 }
210 SubSection.Done();
211 }
212
Sam Cleggb7787fd2017-06-20 04:04:59 +0000213 return 0;
214}
215
216int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000217 writeStringRef(Section.Name, OS);
218 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000219 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000220
Sam Clegg9e1ade92017-06-27 20:27:59 +0000221 SubSectionWriter SubSection(OS);
222
223 encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000224 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000225 encodeULEB128(NameEntry.Index, SubSection.GetStream());
226 writeStringRef(NameEntry.Name, SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000227 }
228
Sam Clegg9e1ade92017-06-27 20:27:59 +0000229 SubSection.Done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000230 }
231 return 0;
232}
233
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000234int WasmWriter::writeSectionContent(raw_ostream &OS,
235 WasmYAML::CustomSection &Section) {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000236 if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
237 if (auto Err = writeSectionContent(OS, *S))
238 return Err;
239 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
240 if (auto Err = writeSectionContent(OS, *S))
241 return Err;
Sam Clegg03cdd122017-05-05 18:12:34 +0000242 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000243 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000244 Section.Payload.writeAsBinary(OS);
245 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000246 return 0;
247}
248
249int WasmWriter::writeSectionContent(raw_ostream &OS,
250 WasmYAML::TypeSection &Section) {
251 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000252 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000253 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000254 if (Sig.Index != ExpectedIndex) {
255 errs() << "Unexpected type index: " << Sig.Index << "\n";
256 return 1;
257 }
258 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000259 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000260 encodeULEB128(Sig.ParamTypes.size(), OS);
261 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000262 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000263 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000264 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000265 } else {
266 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000267 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000268 }
269 }
270 return 0;
271}
272
273int WasmWriter::writeSectionContent(raw_ostream &OS,
274 WasmYAML::ImportSection &Section) {
275 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000276 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000277 writeStringRef(Import.Module, OS);
278 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000279 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000280 switch (Import.Kind) {
281 case wasm::WASM_EXTERNAL_FUNCTION:
282 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000283 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000284 break;
285 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000286 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000287 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000288 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000289 break;
290 case wasm::WASM_EXTERNAL_MEMORY:
291 writeLimits(Import.Memory, OS);
292 break;
293 case wasm::WASM_EXTERNAL_TABLE:
Sam Clegg03e101f2018-03-01 18:06:21 +0000294 writeUint8(OS,Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000295 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000296 break;
297 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000298 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000299 return 1;
300 }
301 }
302 return 0;
303}
304
305int WasmWriter::writeSectionContent(raw_ostream &OS,
306 WasmYAML::FunctionSection &Section) {
307 encodeULEB128(Section.FunctionTypes.size(), OS);
308 for (uint32_t FuncType : Section.FunctionTypes) {
309 encodeULEB128(FuncType, OS);
310 }
311 return 0;
312}
313
314int WasmWriter::writeSectionContent(raw_ostream &OS,
315 WasmYAML::ExportSection &Section) {
316 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000317 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000318 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000319 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000320 encodeULEB128(Export.Index, OS);
321 }
322 return 0;
323}
324
325int WasmWriter::writeSectionContent(raw_ostream &OS,
326 WasmYAML::StartSection &Section) {
327 encodeULEB128(Section.StartFunction, OS);
328 return 0;
329}
330
331int WasmWriter::writeSectionContent(raw_ostream &OS,
332 WasmYAML::TableSection &Section) {
333 encodeULEB128(Section.Tables.size(), OS);
334 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000335 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000336 writeLimits(Table.TableLimits, OS);
337 }
338 return 0;
339}
340
341int WasmWriter::writeSectionContent(raw_ostream &OS,
342 WasmYAML::MemorySection &Section) {
343 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000344 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000345 writeLimits(Mem, OS);
346 }
347 return 0;
348}
349
350int WasmWriter::writeSectionContent(raw_ostream &OS,
351 WasmYAML::GlobalSection &Section) {
352 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000353 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000354 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000355 if (Global.Index != ExpectedIndex) {
356 errs() << "Unexpected global index: " << Global.Index << "\n";
357 return 1;
358 }
359 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000360 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000361 writeUint8(OS, Global.Mutable);
362 writeInitExpr(Global.InitExpr, OS);
363 }
364 return 0;
365}
366
367int WasmWriter::writeSectionContent(raw_ostream &OS,
368 WasmYAML::ElemSection &Section) {
369 encodeULEB128(Section.Segments.size(), OS);
370 for (auto &Segment : Section.Segments) {
371 encodeULEB128(Segment.TableIndex, OS);
372 writeInitExpr(Segment.Offset, OS);
373
374 encodeULEB128(Segment.Functions.size(), OS);
375 for (auto &Function : Segment.Functions) {
376 encodeULEB128(Function, OS);
377 }
378 }
379 return 0;
380}
381
382int WasmWriter::writeSectionContent(raw_ostream &OS,
383 WasmYAML::CodeSection &Section) {
384 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000385 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000386 for (auto &Func : Section.Functions) {
387 std::string OutString;
388 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000389 if (Func.Index != ExpectedIndex) {
390 errs() << "Unexpected function index: " << Func.Index << "\n";
391 return 1;
392 }
393 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000394
395 encodeULEB128(Func.Locals.size(), StringStream);
396 for (auto &LocalDecl : Func.Locals) {
397 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000398 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000399 }
400
401 Func.Body.writeAsBinary(StringStream);
402
403 // Write the section size followed by the content
404 StringStream.flush();
405 encodeULEB128(OutString.size(), OS);
406 OS << OutString;
407 }
408 return 0;
409}
410
411int WasmWriter::writeSectionContent(raw_ostream &OS,
412 WasmYAML::DataSection &Section) {
413 encodeULEB128(Section.Segments.size(), OS);
414 for (auto &Segment : Section.Segments) {
Sam Clegg9c07f942017-07-12 00:24:54 +0000415 encodeULEB128(Segment.MemoryIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000416 writeInitExpr(Segment.Offset, OS);
417 encodeULEB128(Segment.Content.binary_size(), OS);
418 Segment.Content.writeAsBinary(OS);
419 }
420 return 0;
421}
422
423int WasmWriter::writeRelocSection(raw_ostream &OS,
424 WasmYAML::Section &Sec) {
425 StringRef Name;
426 switch (Sec.Type) {
427 case wasm::WASM_SEC_CODE:
428 Name = "reloc.CODE";
429 break;
430 case wasm::WASM_SEC_DATA:
431 Name = "reloc.DATA";
432 break;
433 default:
434 llvm_unreachable("not yet implemented");
435 return 1;
436 }
437
438 writeStringRef(Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000439 writeUint8(OS, Sec.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000440 encodeULEB128(Sec.Relocations.size(), OS);
441
442 for (auto Reloc: Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000443 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000444 encodeULEB128(Reloc.Offset, OS);
445 encodeULEB128(Reloc.Index, OS);
446 switch (Reloc.Type) {
Sam Clegg13a2e892017-09-01 17:32:01 +0000447 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
448 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
449 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000450 encodeULEB128(Reloc.Addend, OS);
451 }
452 }
453 return 0;
454}
455
456
457int WasmWriter::writeWasm(raw_ostream &OS) {
458 // Write headers
459 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
460 writeUint32(OS, Obj.Header.Version);
461
462 // Write each section
Sam Clegge53af7f2018-01-09 21:38:53 +0000463 uint32_t LastType = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000464 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000465 uint32_t Type = Sec->Type;
466 if (Type != wasm::WASM_SEC_CUSTOM) {
467 if (Type < LastType) {
468 errs() << "Out of order section type: " << Type << "\n";
469 return 1;
470 }
471 LastType = Type;
472 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000473
Sam Clegge53af7f2018-01-09 21:38:53 +0000474 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000475 std::string OutString;
476 raw_string_ostream StringStream(OutString);
477 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
478 if (auto Err = writeSectionContent(StringStream, *S))
479 return Err;
480 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
481 if (auto Err = writeSectionContent(StringStream, *S))
482 return Err;
483 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
484 if (auto Err = writeSectionContent(StringStream, *S))
485 return Err;
486 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
487 if (auto Err = writeSectionContent(StringStream, *S))
488 return Err;
489 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
490 if (auto Err = writeSectionContent(StringStream, *S))
491 return Err;
492 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
493 if (auto Err = writeSectionContent(StringStream, *S))
494 return Err;
495 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
496 if (auto Err = writeSectionContent(StringStream, *S))
497 return Err;
498 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
499 if (auto Err = writeSectionContent(StringStream, *S))
500 return Err;
501 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
502 if (auto Err = writeSectionContent(StringStream, *S))
503 return Err;
504 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
505 if (auto Err = writeSectionContent(StringStream, *S))
506 return Err;
507 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
508 if (auto Err = writeSectionContent(StringStream, *S))
509 return Err;
510 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
511 if (auto Err = writeSectionContent(StringStream, *S))
512 return Err;
513 } else {
514 errs() << "Unknown section type: " << Sec->Type << "\n";
515 return 1;
516 }
517 StringStream.flush();
518
519 // Write the section size followed by the content
520 encodeULEB128(OutString.size(), OS);
521 OS << OutString;
522 }
523
524 // write reloc sections for any section that have relocations
525 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
526 if (Sec->Relocations.empty())
527 continue;
528
Sam Clegg03e101f2018-03-01 18:06:21 +0000529 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000530 std::string OutString;
531 raw_string_ostream StringStream(OutString);
532 writeRelocSection(StringStream, *Sec);
533 StringStream.flush();
534
535 encodeULEB128(OutString.size(), OS);
536 OS << OutString;
537 }
538
539 return 0;
540}
541
542int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
543 WasmWriter Writer(Doc);
544
545 return Writer.writeWasm(Out);
546}