blob: bd30f88e9cb5f829bceaa318ea456769c4a3c6f7 [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 {
243 Section.Payload.writeAsBinary(OS);
244 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000245 return 0;
246}
247
248int WasmWriter::writeSectionContent(raw_ostream &OS,
249 WasmYAML::TypeSection &Section) {
250 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000251 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000252 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000253 if (Sig.Index != ExpectedIndex) {
254 errs() << "Unexpected type index: " << Sig.Index << "\n";
255 return 1;
256 }
257 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000258 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000259 encodeULEB128(Sig.ParamTypes.size(), OS);
260 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000261 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000262 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000263 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000264 } else {
265 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000266 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000267 }
268 }
269 return 0;
270}
271
272int WasmWriter::writeSectionContent(raw_ostream &OS,
273 WasmYAML::ImportSection &Section) {
274 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000275 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000276 writeStringRef(Import.Module, OS);
277 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000278 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000279 switch (Import.Kind) {
280 case wasm::WASM_EXTERNAL_FUNCTION:
281 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000282 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000283 break;
284 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000285 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000286 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000287 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000288 break;
289 case wasm::WASM_EXTERNAL_MEMORY:
290 writeLimits(Import.Memory, OS);
291 break;
292 case wasm::WASM_EXTERNAL_TABLE:
Sam Clegg03e101f2018-03-01 18:06:21 +0000293 writeUint8(OS,Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000294 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000295 break;
296 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000297 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000298 return 1;
299 }
300 }
301 return 0;
302}
303
304int WasmWriter::writeSectionContent(raw_ostream &OS,
305 WasmYAML::FunctionSection &Section) {
306 encodeULEB128(Section.FunctionTypes.size(), OS);
307 for (uint32_t FuncType : Section.FunctionTypes) {
308 encodeULEB128(FuncType, OS);
309 }
310 return 0;
311}
312
313int WasmWriter::writeSectionContent(raw_ostream &OS,
314 WasmYAML::ExportSection &Section) {
315 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000316 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000317 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000318 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000319 encodeULEB128(Export.Index, OS);
320 }
321 return 0;
322}
323
324int WasmWriter::writeSectionContent(raw_ostream &OS,
325 WasmYAML::StartSection &Section) {
326 encodeULEB128(Section.StartFunction, OS);
327 return 0;
328}
329
330int WasmWriter::writeSectionContent(raw_ostream &OS,
331 WasmYAML::TableSection &Section) {
332 encodeULEB128(Section.Tables.size(), OS);
333 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000334 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000335 writeLimits(Table.TableLimits, OS);
336 }
337 return 0;
338}
339
340int WasmWriter::writeSectionContent(raw_ostream &OS,
341 WasmYAML::MemorySection &Section) {
342 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000343 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000344 writeLimits(Mem, OS);
345 }
346 return 0;
347}
348
349int WasmWriter::writeSectionContent(raw_ostream &OS,
350 WasmYAML::GlobalSection &Section) {
351 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000352 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000353 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000354 if (Global.Index != ExpectedIndex) {
355 errs() << "Unexpected global index: " << Global.Index << "\n";
356 return 1;
357 }
358 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000359 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000360 writeUint8(OS, Global.Mutable);
361 writeInitExpr(Global.InitExpr, OS);
362 }
363 return 0;
364}
365
366int WasmWriter::writeSectionContent(raw_ostream &OS,
367 WasmYAML::ElemSection &Section) {
368 encodeULEB128(Section.Segments.size(), OS);
369 for (auto &Segment : Section.Segments) {
370 encodeULEB128(Segment.TableIndex, OS);
371 writeInitExpr(Segment.Offset, OS);
372
373 encodeULEB128(Segment.Functions.size(), OS);
374 for (auto &Function : Segment.Functions) {
375 encodeULEB128(Function, OS);
376 }
377 }
378 return 0;
379}
380
381int WasmWriter::writeSectionContent(raw_ostream &OS,
382 WasmYAML::CodeSection &Section) {
383 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000384 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000385 for (auto &Func : Section.Functions) {
386 std::string OutString;
387 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000388 if (Func.Index != ExpectedIndex) {
389 errs() << "Unexpected function index: " << Func.Index << "\n";
390 return 1;
391 }
392 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000393
394 encodeULEB128(Func.Locals.size(), StringStream);
395 for (auto &LocalDecl : Func.Locals) {
396 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000397 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000398 }
399
400 Func.Body.writeAsBinary(StringStream);
401
402 // Write the section size followed by the content
403 StringStream.flush();
404 encodeULEB128(OutString.size(), OS);
405 OS << OutString;
406 }
407 return 0;
408}
409
410int WasmWriter::writeSectionContent(raw_ostream &OS,
411 WasmYAML::DataSection &Section) {
412 encodeULEB128(Section.Segments.size(), OS);
413 for (auto &Segment : Section.Segments) {
Sam Clegg9c07f942017-07-12 00:24:54 +0000414 encodeULEB128(Segment.MemoryIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000415 writeInitExpr(Segment.Offset, OS);
416 encodeULEB128(Segment.Content.binary_size(), OS);
417 Segment.Content.writeAsBinary(OS);
418 }
419 return 0;
420}
421
422int WasmWriter::writeRelocSection(raw_ostream &OS,
423 WasmYAML::Section &Sec) {
424 StringRef Name;
425 switch (Sec.Type) {
426 case wasm::WASM_SEC_CODE:
427 Name = "reloc.CODE";
428 break;
429 case wasm::WASM_SEC_DATA:
430 Name = "reloc.DATA";
431 break;
432 default:
433 llvm_unreachable("not yet implemented");
434 return 1;
435 }
436
437 writeStringRef(Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000438 writeUint8(OS, Sec.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000439 encodeULEB128(Sec.Relocations.size(), OS);
440
441 for (auto Reloc: Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000442 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000443 encodeULEB128(Reloc.Offset, OS);
444 encodeULEB128(Reloc.Index, OS);
445 switch (Reloc.Type) {
Sam Clegg13a2e892017-09-01 17:32:01 +0000446 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
447 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
448 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000449 encodeULEB128(Reloc.Addend, OS);
450 }
451 }
452 return 0;
453}
454
455
456int WasmWriter::writeWasm(raw_ostream &OS) {
457 // Write headers
458 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
459 writeUint32(OS, Obj.Header.Version);
460
461 // Write each section
Sam Clegge53af7f2018-01-09 21:38:53 +0000462 uint32_t LastType = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000463 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000464 uint32_t Type = Sec->Type;
465 if (Type != wasm::WASM_SEC_CUSTOM) {
466 if (Type < LastType) {
467 errs() << "Out of order section type: " << Type << "\n";
468 return 1;
469 }
470 LastType = Type;
471 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000472
Sam Clegge53af7f2018-01-09 21:38:53 +0000473 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000474 std::string OutString;
475 raw_string_ostream StringStream(OutString);
476 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
477 if (auto Err = writeSectionContent(StringStream, *S))
478 return Err;
479 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
480 if (auto Err = writeSectionContent(StringStream, *S))
481 return Err;
482 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
483 if (auto Err = writeSectionContent(StringStream, *S))
484 return Err;
485 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
486 if (auto Err = writeSectionContent(StringStream, *S))
487 return Err;
488 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
489 if (auto Err = writeSectionContent(StringStream, *S))
490 return Err;
491 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
492 if (auto Err = writeSectionContent(StringStream, *S))
493 return Err;
494 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
495 if (auto Err = writeSectionContent(StringStream, *S))
496 return Err;
497 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
498 if (auto Err = writeSectionContent(StringStream, *S))
499 return Err;
500 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
501 if (auto Err = writeSectionContent(StringStream, *S))
502 return Err;
503 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
504 if (auto Err = writeSectionContent(StringStream, *S))
505 return Err;
506 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
507 if (auto Err = writeSectionContent(StringStream, *S))
508 return Err;
509 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
510 if (auto Err = writeSectionContent(StringStream, *S))
511 return Err;
512 } else {
513 errs() << "Unknown section type: " << Sec->Type << "\n";
514 return 1;
515 }
516 StringStream.flush();
517
518 // Write the section size followed by the content
519 encodeULEB128(OutString.size(), OS);
520 OS << OutString;
521 }
522
523 // write reloc sections for any section that have relocations
524 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
525 if (Sec->Relocations.empty())
526 continue;
527
Sam Clegg03e101f2018-03-01 18:06:21 +0000528 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000529 std::string OutString;
530 raw_string_ostream StringStream(OutString);
531 writeRelocSection(StringStream, *Sec);
532 StringStream.flush();
533
534 encodeULEB128(OutString.size(), OS);
535 OS << OutString;
536 }
537
538 return 0;
539}
540
541int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
542 WasmWriter Writer(Doc);
543
544 return Writer.writeWasm(Out);
545}