blob: 7fd0bb069347bc0ddbbaa53a749c8c603493b8aa [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
Sam Clegge4afbc62018-11-14 18:36:24 +000048 int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
Sam Cleggb7787fd2017-06-20 04:04:59 +000049 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
50 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000051 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000052 uint32_t NumImportedFunctions = 0;
53 uint32_t NumImportedGlobals = 0;
Heejin Ahnda419bd2018-11-14 02:46:21 +000054 uint32_t NumImportedEvents = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +000055};
56
57static int writeUint64(raw_ostream &OS, uint64_t Value) {
58 char Data[sizeof(Value)];
59 support::endian::write64le(Data, Value);
60 OS.write(Data, sizeof(Data));
61 return 0;
62}
63
64static int writeUint32(raw_ostream &OS, uint32_t Value) {
65 char Data[sizeof(Value)];
66 support::endian::write32le(Data, Value);
67 OS.write(Data, sizeof(Data));
68 return 0;
69}
70
71static int writeUint8(raw_ostream &OS, uint8_t Value) {
72 char Data[sizeof(Value)];
73 memcpy(Data, &Value, sizeof(Data));
74 OS.write(Data, sizeof(Data));
75 return 0;
76}
77
Sam Clegg03cdd122017-05-05 18:12:34 +000078static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000079 encodeULEB128(Str.size(), OS);
80 OS << Str;
81 return 0;
82}
83
Sam Clegg03cdd122017-05-05 18:12:34 +000084static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +000085 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000086 encodeULEB128(Lim.Initial, OS);
87 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
88 encodeULEB128(Lim.Maximum, OS);
89 return 0;
90}
91
Sam Clegg03cdd122017-05-05 18:12:34 +000092static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000093 writeUint8(OS, InitExpr.Opcode);
94 switch (InitExpr.Opcode) {
95 case wasm::WASM_OPCODE_I32_CONST:
96 encodeSLEB128(InitExpr.Value.Int32, OS);
97 break;
98 case wasm::WASM_OPCODE_I64_CONST:
99 encodeSLEB128(InitExpr.Value.Int64, OS);
100 break;
101 case wasm::WASM_OPCODE_F32_CONST:
102 writeUint32(OS, InitExpr.Value.Float32);
103 break;
104 case wasm::WASM_OPCODE_F64_CONST:
105 writeUint64(OS, InitExpr.Value.Float64);
106 break;
107 case wasm::WASM_OPCODE_GET_GLOBAL:
108 encodeULEB128(InitExpr.Value.Global, OS);
109 break;
110 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000111 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000112 return 1;
113 }
114 writeUint8(OS, wasm::WASM_OPCODE_END);
115 return 0;
116}
117
Sam Clegg9e1ade92017-06-27 20:27:59 +0000118class SubSectionWriter {
119 raw_ostream &OS;
120 std::string OutString;
121 raw_string_ostream StringStream;
Sam Cleggb7787fd2017-06-20 04:04:59 +0000122
Sam Clegg9e1ade92017-06-27 20:27:59 +0000123public:
124 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Cleggb7787fd2017-06-20 04:04:59 +0000125
Sam Clegg9e1ade92017-06-27 20:27:59 +0000126 void Done() {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000127 StringStream.flush();
128 encodeULEB128(OutString.size(), OS);
129 OS << OutString;
Sam Clegg9e1ade92017-06-27 20:27:59 +0000130 OutString.clear();
131 }
132
Heejin Ahnf208f632018-09-05 01:27:38 +0000133 raw_ostream &GetStream() { return StringStream; }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000134};
135
Heejin Ahnf208f632018-09-05 01:27:38 +0000136int WasmWriter::writeSectionContent(raw_ostream &OS,
Sam Clegge4afbc62018-11-14 18:36:24 +0000137 WasmYAML::DylinkSection &Section) {
138 writeStringRef(Section.Name, OS);
139 encodeULEB128(Section.MemorySize, OS);
140 encodeULEB128(Section.MemoryAlignment, OS);
141 encodeULEB128(Section.TableSize, OS);
142 encodeULEB128(Section.TableAlignment, OS);
Sam Clegg03801252018-12-12 23:40:58 +0000143 encodeULEB128(Section.Needed.size(), OS);
144 for (StringRef Needed : Section.Needed) {
145 writeStringRef(Needed, OS);
146 }
Sam Clegge4afbc62018-11-14 18:36:24 +0000147 return 0;
148}
149
150int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnf208f632018-09-05 01:27:38 +0000151 WasmYAML::LinkingSection &Section) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000152 writeStringRef(Section.Name, OS);
Sam Clegg6bb5a412018-04-26 18:15:32 +0000153 encodeULEB128(Section.Version, OS);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000154
155 SubSectionWriter SubSection(OS);
156
Sam Clegg6c899ba2018-02-23 05:08:34 +0000157 // SYMBOL_TABLE subsection
158 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000159 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000160
Sam Clegg6c899ba2018-02-23 05:08:34 +0000161 encodeULEB128(Section.SymbolTable.size(), SubSection.GetStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000162#ifndef NDEBUG
Sam Clegg6c899ba2018-02-23 05:08:34 +0000163 uint32_t SymbolIndex = 0;
164#endif
165 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
166 assert(Info.Index == SymbolIndex++);
Sam Clegg03e101f2018-03-01 18:06:21 +0000167 writeUint8(SubSection.GetStream(), Info.Kind);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000168 encodeULEB128(Info.Flags, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000169 switch (Info.Kind) {
170 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
171 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahnda419bd2018-11-14 02:46:21 +0000172 case wasm::WASM_SYMBOL_TYPE_EVENT:
Sam Clegg6c899ba2018-02-23 05:08:34 +0000173 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
174 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
175 writeStringRef(Info.Name, SubSection.GetStream());
176 break;
177 case wasm::WASM_SYMBOL_TYPE_DATA:
178 writeStringRef(Info.Name, SubSection.GetStream());
179 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
180 encodeULEB128(Info.DataRef.Segment, SubSection.GetStream());
181 encodeULEB128(Info.DataRef.Offset, SubSection.GetStream());
182 encodeULEB128(Info.DataRef.Size, SubSection.GetStream());
183 }
184 break;
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000185 case wasm::WASM_SYMBOL_TYPE_SECTION:
186 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
187 break;
Sam Clegg6c899ba2018-02-23 05:08:34 +0000188 default:
189 llvm_unreachable("unexpected kind");
190 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000191 }
192
193 SubSection.Done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000194 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000195
196 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000197 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000198 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Sam Clegg63ebb812017-09-29 16:50:08 +0000199 encodeULEB128(Section.SegmentInfos.size(), SubSection.GetStream());
200 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Sam Clegg63ebb812017-09-29 16:50:08 +0000201 writeStringRef(SegmentInfo.Name, SubSection.GetStream());
202 encodeULEB128(SegmentInfo.Alignment, SubSection.GetStream());
203 encodeULEB128(SegmentInfo.Flags, SubSection.GetStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000204 }
205 SubSection.Done();
206 }
Sam Clegg42739982017-12-14 21:10:03 +0000207
208 // INIT_FUNCS subsection
209 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000210 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Sam Clegg42739982017-12-14 21:10:03 +0000211 encodeULEB128(Section.InitFunctions.size(), SubSection.GetStream());
212 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
213 encodeULEB128(Func.Priority, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000214 encodeULEB128(Func.Symbol, SubSection.GetStream());
Sam Clegg42739982017-12-14 21:10:03 +0000215 }
216 SubSection.Done();
217 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000218
219 // COMDAT_INFO subsection
220 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000221 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Sam Cleggea7cace2018-01-09 23:43:14 +0000222 encodeULEB128(Section.Comdats.size(), SubSection.GetStream());
223 for (const auto &C : Section.Comdats) {
224 writeStringRef(C.Name, SubSection.GetStream());
225 encodeULEB128(0, SubSection.GetStream()); // flags for future use
226 encodeULEB128(C.Entries.size(), SubSection.GetStream());
227 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000228 writeUint8(SubSection.GetStream(), Entry.Kind);
Sam Cleggea7cace2018-01-09 23:43:14 +0000229 encodeULEB128(Entry.Index, SubSection.GetStream());
230 }
231 }
232 SubSection.Done();
233 }
234
Sam Cleggb7787fd2017-06-20 04:04:59 +0000235 return 0;
236}
237
Heejin Ahnf208f632018-09-05 01:27:38 +0000238int WasmWriter::writeSectionContent(raw_ostream &OS,
239 WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000240 writeStringRef(Section.Name, OS);
241 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000242 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000243
Sam Clegg9e1ade92017-06-27 20:27:59 +0000244 SubSectionWriter SubSection(OS);
245
246 encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000247 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000248 encodeULEB128(NameEntry.Index, SubSection.GetStream());
249 writeStringRef(NameEntry.Name, SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000250 }
251
Sam Clegg9e1ade92017-06-27 20:27:59 +0000252 SubSection.Done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000253 }
254 return 0;
255}
256
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000257int WasmWriter::writeSectionContent(raw_ostream &OS,
258 WasmYAML::CustomSection &Section) {
Sam Clegge4afbc62018-11-14 18:36:24 +0000259 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
260 if (auto Err = writeSectionContent(OS, *S))
261 return Err;
262 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000263 if (auto Err = writeSectionContent(OS, *S))
264 return Err;
265 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
266 if (auto Err = writeSectionContent(OS, *S))
267 return Err;
Sam Clegg03cdd122017-05-05 18:12:34 +0000268 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000269 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000270 Section.Payload.writeAsBinary(OS);
271 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000272 return 0;
273}
274
275int WasmWriter::writeSectionContent(raw_ostream &OS,
276 WasmYAML::TypeSection &Section) {
277 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000278 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000279 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000280 if (Sig.Index != ExpectedIndex) {
281 errs() << "Unexpected type index: " << Sig.Index << "\n";
282 return 1;
283 }
284 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000285 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000286 encodeULEB128(Sig.ParamTypes.size(), OS);
287 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000288 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000289 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000290 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000291 } else {
292 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000293 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000294 }
295 }
296 return 0;
297}
298
299int WasmWriter::writeSectionContent(raw_ostream &OS,
300 WasmYAML::ImportSection &Section) {
301 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000302 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000303 writeStringRef(Import.Module, OS);
304 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000305 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000306 switch (Import.Kind) {
307 case wasm::WASM_EXTERNAL_FUNCTION:
308 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000309 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000310 break;
311 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000312 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000313 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000314 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000315 break;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000316 case wasm::WASM_EXTERNAL_EVENT:
317 writeUint32(OS, Import.EventImport.Attribute);
318 writeUint32(OS, Import.EventImport.SigIndex);
319 NumImportedGlobals++;
320 break;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000321 case wasm::WASM_EXTERNAL_MEMORY:
322 writeLimits(Import.Memory, OS);
323 break;
324 case wasm::WASM_EXTERNAL_TABLE:
Heejin Ahnf208f632018-09-05 01:27:38 +0000325 writeUint8(OS, Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000326 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000327 break;
328 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000329 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000330 return 1;
331 }
332 }
333 return 0;
334}
335
336int WasmWriter::writeSectionContent(raw_ostream &OS,
337 WasmYAML::FunctionSection &Section) {
338 encodeULEB128(Section.FunctionTypes.size(), OS);
339 for (uint32_t FuncType : Section.FunctionTypes) {
340 encodeULEB128(FuncType, OS);
341 }
342 return 0;
343}
344
345int WasmWriter::writeSectionContent(raw_ostream &OS,
346 WasmYAML::ExportSection &Section) {
347 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000348 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000349 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000350 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000351 encodeULEB128(Export.Index, OS);
352 }
353 return 0;
354}
355
356int WasmWriter::writeSectionContent(raw_ostream &OS,
357 WasmYAML::StartSection &Section) {
358 encodeULEB128(Section.StartFunction, OS);
359 return 0;
360}
361
362int WasmWriter::writeSectionContent(raw_ostream &OS,
363 WasmYAML::TableSection &Section) {
364 encodeULEB128(Section.Tables.size(), OS);
365 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000366 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000367 writeLimits(Table.TableLimits, OS);
368 }
369 return 0;
370}
371
372int WasmWriter::writeSectionContent(raw_ostream &OS,
373 WasmYAML::MemorySection &Section) {
374 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000375 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000376 writeLimits(Mem, OS);
377 }
378 return 0;
379}
380
381int WasmWriter::writeSectionContent(raw_ostream &OS,
382 WasmYAML::GlobalSection &Section) {
383 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000384 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000385 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000386 if (Global.Index != ExpectedIndex) {
387 errs() << "Unexpected global index: " << Global.Index << "\n";
388 return 1;
389 }
390 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000391 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000392 writeUint8(OS, Global.Mutable);
393 writeInitExpr(Global.InitExpr, OS);
394 }
395 return 0;
396}
397
398int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnda419bd2018-11-14 02:46:21 +0000399 WasmYAML::EventSection &Section) {
400 encodeULEB128(Section.Events.size(), OS);
401 uint32_t ExpectedIndex = NumImportedEvents;
402 for (auto &Event : Section.Events) {
403 if (Event.Index != ExpectedIndex) {
404 errs() << "Unexpected event index: " << Event.Index << "\n";
405 return 1;
406 }
407 ++ExpectedIndex;
408 encodeULEB128(Event.Attribute, OS);
409 encodeULEB128(Event.SigIndex, OS);
410 }
411 return 0;
412}
413
414int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000415 WasmYAML::ElemSection &Section) {
416 encodeULEB128(Section.Segments.size(), OS);
417 for (auto &Segment : Section.Segments) {
418 encodeULEB128(Segment.TableIndex, OS);
419 writeInitExpr(Segment.Offset, OS);
420
421 encodeULEB128(Segment.Functions.size(), OS);
422 for (auto &Function : Segment.Functions) {
423 encodeULEB128(Function, OS);
424 }
425 }
426 return 0;
427}
428
429int WasmWriter::writeSectionContent(raw_ostream &OS,
430 WasmYAML::CodeSection &Section) {
431 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000432 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000433 for (auto &Func : Section.Functions) {
434 std::string OutString;
435 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000436 if (Func.Index != ExpectedIndex) {
437 errs() << "Unexpected function index: " << Func.Index << "\n";
438 return 1;
439 }
440 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000441
442 encodeULEB128(Func.Locals.size(), StringStream);
443 for (auto &LocalDecl : Func.Locals) {
444 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000445 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000446 }
447
448 Func.Body.writeAsBinary(StringStream);
449
450 // Write the section size followed by the content
451 StringStream.flush();
452 encodeULEB128(OutString.size(), OS);
453 OS << OutString;
454 }
455 return 0;
456}
457
458int WasmWriter::writeSectionContent(raw_ostream &OS,
459 WasmYAML::DataSection &Section) {
460 encodeULEB128(Section.Segments.size(), OS);
461 for (auto &Segment : Section.Segments) {
Sam Clegg9c07f942017-07-12 00:24:54 +0000462 encodeULEB128(Segment.MemoryIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000463 writeInitExpr(Segment.Offset, OS);
464 encodeULEB128(Segment.Content.binary_size(), OS);
465 Segment.Content.writeAsBinary(OS);
466 }
467 return 0;
468}
469
Sam Clegg6f08c842018-04-24 18:11:36 +0000470int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
471 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000472 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000473 case wasm::WASM_SEC_CODE:
474 writeStringRef("reloc.CODE", OS);
475 break;
476 case wasm::WASM_SEC_DATA:
477 writeStringRef("reloc.DATA", OS);
478 break;
479 case wasm::WASM_SEC_CUSTOM: {
480 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
481 if (!CustomSection->Name.startswith(".debug_")) {
482 llvm_unreachable("not yet implemented (only for debug sections)");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000483 return 1;
Heejin Ahnf208f632018-09-05 01:27:38 +0000484 }
485
486 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
487 break;
488 }
489 default:
490 llvm_unreachable("not yet implemented");
491 return 1;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000492 }
493
Sam Clegg6f08c842018-04-24 18:11:36 +0000494 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000495 encodeULEB128(Sec.Relocations.size(), OS);
496
Heejin Ahnf208f632018-09-05 01:27:38 +0000497 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000498 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000499 encodeULEB128(Reloc.Offset, OS);
500 encodeULEB128(Reloc.Index, OS);
501 switch (Reloc.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000502 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
503 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
504 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
505 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
506 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
507 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000508 }
509 }
510 return 0;
511}
512
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000513int WasmWriter::writeWasm(raw_ostream &OS) {
514 // Write headers
515 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
516 writeUint32(OS, Obj.Header.Version);
517
518 // Write each section
519 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000520 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000521 std::string OutString;
522 raw_string_ostream StringStream(OutString);
523 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
524 if (auto Err = writeSectionContent(StringStream, *S))
525 return Err;
526 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
527 if (auto Err = writeSectionContent(StringStream, *S))
528 return Err;
529 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
530 if (auto Err = writeSectionContent(StringStream, *S))
531 return Err;
532 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
533 if (auto Err = writeSectionContent(StringStream, *S))
534 return Err;
535 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
536 if (auto Err = writeSectionContent(StringStream, *S))
537 return Err;
538 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
539 if (auto Err = writeSectionContent(StringStream, *S))
540 return Err;
541 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
542 if (auto Err = writeSectionContent(StringStream, *S))
543 return Err;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000544 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
545 if (auto Err = writeSectionContent(StringStream, *S))
546 return Err;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000547 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
548 if (auto Err = writeSectionContent(StringStream, *S))
549 return Err;
550 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
551 if (auto Err = writeSectionContent(StringStream, *S))
552 return Err;
553 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
554 if (auto Err = writeSectionContent(StringStream, *S))
555 return Err;
556 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
557 if (auto Err = writeSectionContent(StringStream, *S))
558 return Err;
559 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
560 if (auto Err = writeSectionContent(StringStream, *S))
561 return Err;
562 } else {
563 errs() << "Unknown section type: " << Sec->Type << "\n";
564 return 1;
565 }
566 StringStream.flush();
567
568 // Write the section size followed by the content
569 encodeULEB128(OutString.size(), OS);
570 OS << OutString;
571 }
572
573 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000574 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000575 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000576 if (Sec->Relocations.empty()) {
577 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000578 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000579 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000580
Sam Clegg03e101f2018-03-01 18:06:21 +0000581 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000582 std::string OutString;
583 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000584 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000585 StringStream.flush();
586
587 encodeULEB128(OutString.size(), OS);
588 OS << OutString;
589 }
590
591 return 0;
592}
593
594int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
595 WasmWriter Writer(Doc);
596
597 return Writer.writeWasm(Out);
598}