blob: 4a9269d96a1ace68112f2be31de3af8756f69928 [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
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000011/// The Wasm component of yaml2obj.
Derek Schuffd3d84fd2017-03-30 19:44:09 +000012///
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);
Heejin Ahnda419bd2018-11-14 02:46:21 +000040 int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000041 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
42 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
43 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
44 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
45 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
46
Sam Cleggb7787fd2017-06-20 04:04:59 +000047 // Custom section types
48 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
49 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000050 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000051 uint32_t NumImportedFunctions = 0;
52 uint32_t NumImportedGlobals = 0;
Heejin Ahnda419bd2018-11-14 02:46:21 +000053 uint32_t NumImportedEvents = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +000054};
55
56static int writeUint64(raw_ostream &OS, uint64_t Value) {
57 char Data[sizeof(Value)];
58 support::endian::write64le(Data, Value);
59 OS.write(Data, sizeof(Data));
60 return 0;
61}
62
63static int writeUint32(raw_ostream &OS, uint32_t Value) {
64 char Data[sizeof(Value)];
65 support::endian::write32le(Data, Value);
66 OS.write(Data, sizeof(Data));
67 return 0;
68}
69
70static int writeUint8(raw_ostream &OS, uint8_t Value) {
71 char Data[sizeof(Value)];
72 memcpy(Data, &Value, sizeof(Data));
73 OS.write(Data, sizeof(Data));
74 return 0;
75}
76
Sam Clegg03cdd122017-05-05 18:12:34 +000077static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000078 encodeULEB128(Str.size(), OS);
79 OS << Str;
80 return 0;
81}
82
Sam Clegg03cdd122017-05-05 18:12:34 +000083static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +000084 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000085 encodeULEB128(Lim.Initial, OS);
86 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
87 encodeULEB128(Lim.Maximum, OS);
88 return 0;
89}
90
Sam Clegg03cdd122017-05-05 18:12:34 +000091static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000092 writeUint8(OS, InitExpr.Opcode);
93 switch (InitExpr.Opcode) {
94 case wasm::WASM_OPCODE_I32_CONST:
95 encodeSLEB128(InitExpr.Value.Int32, OS);
96 break;
97 case wasm::WASM_OPCODE_I64_CONST:
98 encodeSLEB128(InitExpr.Value.Int64, OS);
99 break;
100 case wasm::WASM_OPCODE_F32_CONST:
101 writeUint32(OS, InitExpr.Value.Float32);
102 break;
103 case wasm::WASM_OPCODE_F64_CONST:
104 writeUint64(OS, InitExpr.Value.Float64);
105 break;
106 case wasm::WASM_OPCODE_GET_GLOBAL:
107 encodeULEB128(InitExpr.Value.Global, OS);
108 break;
109 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000110 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000111 return 1;
112 }
113 writeUint8(OS, wasm::WASM_OPCODE_END);
114 return 0;
115}
116
Sam Clegg9e1ade92017-06-27 20:27:59 +0000117class SubSectionWriter {
118 raw_ostream &OS;
119 std::string OutString;
120 raw_string_ostream StringStream;
Sam Cleggb7787fd2017-06-20 04:04:59 +0000121
Sam Clegg9e1ade92017-06-27 20:27:59 +0000122public:
123 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Cleggb7787fd2017-06-20 04:04:59 +0000124
Sam Clegg9e1ade92017-06-27 20:27:59 +0000125 void Done() {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000126 StringStream.flush();
127 encodeULEB128(OutString.size(), OS);
128 OS << OutString;
Sam Clegg9e1ade92017-06-27 20:27:59 +0000129 OutString.clear();
130 }
131
Heejin Ahnf208f632018-09-05 01:27:38 +0000132 raw_ostream &GetStream() { return StringStream; }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000133};
134
Heejin Ahnf208f632018-09-05 01:27:38 +0000135int WasmWriter::writeSectionContent(raw_ostream &OS,
136 WasmYAML::LinkingSection &Section) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000137 writeStringRef(Section.Name, OS);
Sam Clegg6bb5a412018-04-26 18:15:32 +0000138 encodeULEB128(Section.Version, OS);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000139
140 SubSectionWriter SubSection(OS);
141
Sam Clegg6c899ba2018-02-23 05:08:34 +0000142 // SYMBOL_TABLE subsection
143 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000144 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000145
Sam Clegg6c899ba2018-02-23 05:08:34 +0000146 encodeULEB128(Section.SymbolTable.size(), SubSection.GetStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000147#ifndef NDEBUG
Sam Clegg6c899ba2018-02-23 05:08:34 +0000148 uint32_t SymbolIndex = 0;
149#endif
150 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
151 assert(Info.Index == SymbolIndex++);
Sam Clegg03e101f2018-03-01 18:06:21 +0000152 writeUint8(SubSection.GetStream(), Info.Kind);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000153 encodeULEB128(Info.Flags, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000154 switch (Info.Kind) {
155 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
156 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahnda419bd2018-11-14 02:46:21 +0000157 case wasm::WASM_SYMBOL_TYPE_EVENT:
Sam Clegg6c899ba2018-02-23 05:08:34 +0000158 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
159 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
160 writeStringRef(Info.Name, SubSection.GetStream());
161 break;
162 case wasm::WASM_SYMBOL_TYPE_DATA:
163 writeStringRef(Info.Name, SubSection.GetStream());
164 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
165 encodeULEB128(Info.DataRef.Segment, SubSection.GetStream());
166 encodeULEB128(Info.DataRef.Offset, SubSection.GetStream());
167 encodeULEB128(Info.DataRef.Size, SubSection.GetStream());
168 }
169 break;
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000170 case wasm::WASM_SYMBOL_TYPE_SECTION:
171 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
172 break;
Sam Clegg6c899ba2018-02-23 05:08:34 +0000173 default:
174 llvm_unreachable("unexpected kind");
175 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000176 }
177
178 SubSection.Done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000179 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000180
181 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000182 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000183 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Sam Clegg63ebb812017-09-29 16:50:08 +0000184 encodeULEB128(Section.SegmentInfos.size(), SubSection.GetStream());
185 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Sam Clegg63ebb812017-09-29 16:50:08 +0000186 writeStringRef(SegmentInfo.Name, SubSection.GetStream());
187 encodeULEB128(SegmentInfo.Alignment, SubSection.GetStream());
188 encodeULEB128(SegmentInfo.Flags, SubSection.GetStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000189 }
190 SubSection.Done();
191 }
Sam Clegg42739982017-12-14 21:10:03 +0000192
193 // INIT_FUNCS subsection
194 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000195 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Sam Clegg42739982017-12-14 21:10:03 +0000196 encodeULEB128(Section.InitFunctions.size(), SubSection.GetStream());
197 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
198 encodeULEB128(Func.Priority, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000199 encodeULEB128(Func.Symbol, SubSection.GetStream());
Sam Clegg42739982017-12-14 21:10:03 +0000200 }
201 SubSection.Done();
202 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000203
204 // COMDAT_INFO subsection
205 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000206 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Sam Cleggea7cace2018-01-09 23:43:14 +0000207 encodeULEB128(Section.Comdats.size(), SubSection.GetStream());
208 for (const auto &C : Section.Comdats) {
209 writeStringRef(C.Name, SubSection.GetStream());
210 encodeULEB128(0, SubSection.GetStream()); // flags for future use
211 encodeULEB128(C.Entries.size(), SubSection.GetStream());
212 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000213 writeUint8(SubSection.GetStream(), Entry.Kind);
Sam Cleggea7cace2018-01-09 23:43:14 +0000214 encodeULEB128(Entry.Index, SubSection.GetStream());
215 }
216 }
217 SubSection.Done();
218 }
219
Sam Cleggb7787fd2017-06-20 04:04:59 +0000220 return 0;
221}
222
Heejin Ahnf208f632018-09-05 01:27:38 +0000223int WasmWriter::writeSectionContent(raw_ostream &OS,
224 WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000225 writeStringRef(Section.Name, OS);
226 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000227 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000228
Sam Clegg9e1ade92017-06-27 20:27:59 +0000229 SubSectionWriter SubSection(OS);
230
231 encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000232 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000233 encodeULEB128(NameEntry.Index, SubSection.GetStream());
234 writeStringRef(NameEntry.Name, SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000235 }
236
Sam Clegg9e1ade92017-06-27 20:27:59 +0000237 SubSection.Done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000238 }
239 return 0;
240}
241
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000242int WasmWriter::writeSectionContent(raw_ostream &OS,
243 WasmYAML::CustomSection &Section) {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000244 if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
245 if (auto Err = writeSectionContent(OS, *S))
246 return Err;
247 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
248 if (auto Err = writeSectionContent(OS, *S))
249 return Err;
Sam Clegg03cdd122017-05-05 18:12:34 +0000250 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000251 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000252 Section.Payload.writeAsBinary(OS);
253 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000254 return 0;
255}
256
257int WasmWriter::writeSectionContent(raw_ostream &OS,
258 WasmYAML::TypeSection &Section) {
259 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000260 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000261 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000262 if (Sig.Index != ExpectedIndex) {
263 errs() << "Unexpected type index: " << Sig.Index << "\n";
264 return 1;
265 }
266 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000267 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000268 encodeULEB128(Sig.ParamTypes.size(), OS);
269 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000270 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000271 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000272 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000273 } else {
274 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000275 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000276 }
277 }
278 return 0;
279}
280
281int WasmWriter::writeSectionContent(raw_ostream &OS,
282 WasmYAML::ImportSection &Section) {
283 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000284 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000285 writeStringRef(Import.Module, OS);
286 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000287 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000288 switch (Import.Kind) {
289 case wasm::WASM_EXTERNAL_FUNCTION:
290 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000291 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000292 break;
293 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000294 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000295 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000296 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000297 break;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000298 case wasm::WASM_EXTERNAL_EVENT:
299 writeUint32(OS, Import.EventImport.Attribute);
300 writeUint32(OS, Import.EventImport.SigIndex);
301 NumImportedGlobals++;
302 break;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000303 case wasm::WASM_EXTERNAL_MEMORY:
304 writeLimits(Import.Memory, OS);
305 break;
306 case wasm::WASM_EXTERNAL_TABLE:
Heejin Ahnf208f632018-09-05 01:27:38 +0000307 writeUint8(OS, Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000308 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000309 break;
310 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000311 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000312 return 1;
313 }
314 }
315 return 0;
316}
317
318int WasmWriter::writeSectionContent(raw_ostream &OS,
319 WasmYAML::FunctionSection &Section) {
320 encodeULEB128(Section.FunctionTypes.size(), OS);
321 for (uint32_t FuncType : Section.FunctionTypes) {
322 encodeULEB128(FuncType, OS);
323 }
324 return 0;
325}
326
327int WasmWriter::writeSectionContent(raw_ostream &OS,
328 WasmYAML::ExportSection &Section) {
329 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000330 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000331 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000332 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000333 encodeULEB128(Export.Index, OS);
334 }
335 return 0;
336}
337
338int WasmWriter::writeSectionContent(raw_ostream &OS,
339 WasmYAML::StartSection &Section) {
340 encodeULEB128(Section.StartFunction, OS);
341 return 0;
342}
343
344int WasmWriter::writeSectionContent(raw_ostream &OS,
345 WasmYAML::TableSection &Section) {
346 encodeULEB128(Section.Tables.size(), OS);
347 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000348 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000349 writeLimits(Table.TableLimits, OS);
350 }
351 return 0;
352}
353
354int WasmWriter::writeSectionContent(raw_ostream &OS,
355 WasmYAML::MemorySection &Section) {
356 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000357 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000358 writeLimits(Mem, OS);
359 }
360 return 0;
361}
362
363int WasmWriter::writeSectionContent(raw_ostream &OS,
364 WasmYAML::GlobalSection &Section) {
365 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000366 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000367 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000368 if (Global.Index != ExpectedIndex) {
369 errs() << "Unexpected global index: " << Global.Index << "\n";
370 return 1;
371 }
372 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000373 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000374 writeUint8(OS, Global.Mutable);
375 writeInitExpr(Global.InitExpr, OS);
376 }
377 return 0;
378}
379
380int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnda419bd2018-11-14 02:46:21 +0000381 WasmYAML::EventSection &Section) {
382 encodeULEB128(Section.Events.size(), OS);
383 uint32_t ExpectedIndex = NumImportedEvents;
384 for (auto &Event : Section.Events) {
385 if (Event.Index != ExpectedIndex) {
386 errs() << "Unexpected event index: " << Event.Index << "\n";
387 return 1;
388 }
389 ++ExpectedIndex;
390 encodeULEB128(Event.Attribute, OS);
391 encodeULEB128(Event.SigIndex, OS);
392 }
393 return 0;
394}
395
396int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000397 WasmYAML::ElemSection &Section) {
398 encodeULEB128(Section.Segments.size(), OS);
399 for (auto &Segment : Section.Segments) {
400 encodeULEB128(Segment.TableIndex, OS);
401 writeInitExpr(Segment.Offset, OS);
402
403 encodeULEB128(Segment.Functions.size(), OS);
404 for (auto &Function : Segment.Functions) {
405 encodeULEB128(Function, OS);
406 }
407 }
408 return 0;
409}
410
411int WasmWriter::writeSectionContent(raw_ostream &OS,
412 WasmYAML::CodeSection &Section) {
413 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000414 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000415 for (auto &Func : Section.Functions) {
416 std::string OutString;
417 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000418 if (Func.Index != ExpectedIndex) {
419 errs() << "Unexpected function index: " << Func.Index << "\n";
420 return 1;
421 }
422 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000423
424 encodeULEB128(Func.Locals.size(), StringStream);
425 for (auto &LocalDecl : Func.Locals) {
426 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000427 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000428 }
429
430 Func.Body.writeAsBinary(StringStream);
431
432 // Write the section size followed by the content
433 StringStream.flush();
434 encodeULEB128(OutString.size(), OS);
435 OS << OutString;
436 }
437 return 0;
438}
439
440int WasmWriter::writeSectionContent(raw_ostream &OS,
441 WasmYAML::DataSection &Section) {
442 encodeULEB128(Section.Segments.size(), OS);
443 for (auto &Segment : Section.Segments) {
Sam Clegg9c07f942017-07-12 00:24:54 +0000444 encodeULEB128(Segment.MemoryIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000445 writeInitExpr(Segment.Offset, OS);
446 encodeULEB128(Segment.Content.binary_size(), OS);
447 Segment.Content.writeAsBinary(OS);
448 }
449 return 0;
450}
451
Sam Clegg6f08c842018-04-24 18:11:36 +0000452int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
453 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000454 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000455 case wasm::WASM_SEC_CODE:
456 writeStringRef("reloc.CODE", OS);
457 break;
458 case wasm::WASM_SEC_DATA:
459 writeStringRef("reloc.DATA", OS);
460 break;
461 case wasm::WASM_SEC_CUSTOM: {
462 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
463 if (!CustomSection->Name.startswith(".debug_")) {
464 llvm_unreachable("not yet implemented (only for debug sections)");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000465 return 1;
Heejin Ahnf208f632018-09-05 01:27:38 +0000466 }
467
468 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
469 break;
470 }
471 default:
472 llvm_unreachable("not yet implemented");
473 return 1;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000474 }
475
Sam Clegg6f08c842018-04-24 18:11:36 +0000476 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000477 encodeULEB128(Sec.Relocations.size(), OS);
478
Heejin Ahnf208f632018-09-05 01:27:38 +0000479 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000480 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000481 encodeULEB128(Reloc.Offset, OS);
482 encodeULEB128(Reloc.Index, OS);
483 switch (Reloc.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000484 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
485 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
486 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
487 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
488 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
489 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000490 }
491 }
492 return 0;
493}
494
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000495int WasmWriter::writeWasm(raw_ostream &OS) {
496 // Write headers
497 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
498 writeUint32(OS, Obj.Header.Version);
499
500 // Write each section
501 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000502 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000503 std::string OutString;
504 raw_string_ostream StringStream(OutString);
505 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
506 if (auto Err = writeSectionContent(StringStream, *S))
507 return Err;
508 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
509 if (auto Err = writeSectionContent(StringStream, *S))
510 return Err;
511 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
512 if (auto Err = writeSectionContent(StringStream, *S))
513 return Err;
514 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
515 if (auto Err = writeSectionContent(StringStream, *S))
516 return Err;
517 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
518 if (auto Err = writeSectionContent(StringStream, *S))
519 return Err;
520 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
521 if (auto Err = writeSectionContent(StringStream, *S))
522 return Err;
523 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
524 if (auto Err = writeSectionContent(StringStream, *S))
525 return Err;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000526 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
527 if (auto Err = writeSectionContent(StringStream, *S))
528 return Err;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000529 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
530 if (auto Err = writeSectionContent(StringStream, *S))
531 return Err;
532 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
533 if (auto Err = writeSectionContent(StringStream, *S))
534 return Err;
535 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
536 if (auto Err = writeSectionContent(StringStream, *S))
537 return Err;
538 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
539 if (auto Err = writeSectionContent(StringStream, *S))
540 return Err;
541 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
542 if (auto Err = writeSectionContent(StringStream, *S))
543 return Err;
544 } else {
545 errs() << "Unknown section type: " << Sec->Type << "\n";
546 return 1;
547 }
548 StringStream.flush();
549
550 // Write the section size followed by the content
551 encodeULEB128(OutString.size(), OS);
552 OS << OutString;
553 }
554
555 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000556 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000557 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000558 if (Sec->Relocations.empty()) {
559 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000560 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000561 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000562
Sam Clegg03e101f2018-03-01 18:06:21 +0000563 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000564 std::string OutString;
565 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000566 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000567 StringStream.flush();
568
569 encodeULEB128(OutString.size(), OS);
570 OS << OutString;
571 }
572
573 return 0;
574}
575
576int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
577 WasmWriter Writer(Doc);
578
579 return Writer.writeWasm(Out);
580}