blob: 7d08e62bcedd816f896e0af90db82b7e2203ed47 [file] [log] [blame]
Derek Schuff349a48f2017-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 Prantl26b584c2018-05-01 15:54:18 +000011/// The Wasm component of yaml2obj.
Derek Schuff349a48f2017-03-30 19:44:09 +000012///
13//===----------------------------------------------------------------------===//
14//
Sam Cleggd5784792018-02-23 05:08:34 +000015
Heejin Ahne2f3e502018-12-15 00:58:12 +000016#include "llvm/Object/Wasm.h"
Derek Schuff349a48f2017-03-30 19:44:09 +000017#include "llvm/ObjectYAML/ObjectYAML.h"
18#include "llvm/Support/Endian.h"
19#include "llvm/Support/LEB128.h"
20
21using namespace llvm;
22
23/// This parses a yaml stream that represents a Wasm object file.
24/// See docs/yaml2obj for the yaml scheema.
25class WasmWriter {
26public:
27 WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
28 int writeWasm(raw_ostream &OS);
Sam Clegg1e975c12017-06-20 04:04:59 +000029
30private:
Sam Clegg194a4e02018-04-24 18:11:36 +000031 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
32 uint32_t SectionIndex);
Sam Cleggafe81112017-05-05 18:12:34 +000033
Derek Schuff349a48f2017-03-30 19:44:09 +000034 int writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
35 int writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
36 int writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
37 int writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
38 int writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
39 int writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
40 int writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
Heejin Ahn8bcdd042018-11-14 02:46:21 +000041 int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
Derek Schuff349a48f2017-03-30 19:44:09 +000042 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
43 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
44 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
45 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
46 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
47
Sam Clegg1e975c12017-06-20 04:04:59 +000048 // Custom section types
Sam Clegg45c215a2018-11-14 18:36:24 +000049 int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
Sam Clegg1e975c12017-06-20 04:04:59 +000050 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
51 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
Derek Schuff349a48f2017-03-30 19:44:09 +000052 WasmYAML::Object &Obj;
Sam Clegg6b54fc32018-01-09 21:38:53 +000053 uint32_t NumImportedFunctions = 0;
54 uint32_t NumImportedGlobals = 0;
Heejin Ahn8bcdd042018-11-14 02:46:21 +000055 uint32_t NumImportedEvents = 0;
Derek Schuff349a48f2017-03-30 19:44:09 +000056};
57
58static int writeUint64(raw_ostream &OS, uint64_t Value) {
59 char Data[sizeof(Value)];
60 support::endian::write64le(Data, Value);
61 OS.write(Data, sizeof(Data));
62 return 0;
63}
64
65static int writeUint32(raw_ostream &OS, uint32_t Value) {
66 char Data[sizeof(Value)];
67 support::endian::write32le(Data, Value);
68 OS.write(Data, sizeof(Data));
69 return 0;
70}
71
72static int writeUint8(raw_ostream &OS, uint8_t Value) {
73 char Data[sizeof(Value)];
74 memcpy(Data, &Value, sizeof(Data));
75 OS.write(Data, sizeof(Data));
76 return 0;
77}
78
Sam Cleggafe81112017-05-05 18:12:34 +000079static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuff349a48f2017-03-30 19:44:09 +000080 encodeULEB128(Str.size(), OS);
81 OS << Str;
82 return 0;
83}
84
Sam Cleggafe81112017-05-05 18:12:34 +000085static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg9f474de2018-03-01 18:06:21 +000086 writeUint8(OS, Lim.Flags);
Derek Schuff349a48f2017-03-30 19:44:09 +000087 encodeULEB128(Lim.Initial, OS);
88 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
89 encodeULEB128(Lim.Maximum, OS);
90 return 0;
91}
92
Sam Cleggafe81112017-05-05 18:12:34 +000093static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuff349a48f2017-03-30 19:44:09 +000094 writeUint8(OS, InitExpr.Opcode);
95 switch (InitExpr.Opcode) {
96 case wasm::WASM_OPCODE_I32_CONST:
97 encodeSLEB128(InitExpr.Value.Int32, OS);
98 break;
99 case wasm::WASM_OPCODE_I64_CONST:
100 encodeSLEB128(InitExpr.Value.Int64, OS);
101 break;
102 case wasm::WASM_OPCODE_F32_CONST:
103 writeUint32(OS, InitExpr.Value.Float32);
104 break;
105 case wasm::WASM_OPCODE_F64_CONST:
106 writeUint64(OS, InitExpr.Value.Float64);
107 break;
Thomas Lively37a984b2019-01-08 06:25:55 +0000108 case wasm::WASM_OPCODE_GLOBAL_GET:
Derek Schuff349a48f2017-03-30 19:44:09 +0000109 encodeULEB128(InitExpr.Value.Global, OS);
110 break;
111 default:
Sam Clegg6b54fc32018-01-09 21:38:53 +0000112 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuff349a48f2017-03-30 19:44:09 +0000113 return 1;
114 }
115 writeUint8(OS, wasm::WASM_OPCODE_END);
116 return 0;
117}
118
Sam Clegg49ab5d52017-06-27 20:27:59 +0000119class SubSectionWriter {
120 raw_ostream &OS;
121 std::string OutString;
122 raw_string_ostream StringStream;
Sam Clegg1e975c12017-06-20 04:04:59 +0000123
Sam Clegg49ab5d52017-06-27 20:27:59 +0000124public:
125 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Clegg1e975c12017-06-20 04:04:59 +0000126
Sam Clegg49ab5d52017-06-27 20:27:59 +0000127 void Done() {
Sam Clegg1e975c12017-06-20 04:04:59 +0000128 StringStream.flush();
129 encodeULEB128(OutString.size(), OS);
130 OS << OutString;
Sam Clegg49ab5d52017-06-27 20:27:59 +0000131 OutString.clear();
132 }
133
Heejin Ahn581d2312018-09-05 01:27:38 +0000134 raw_ostream &GetStream() { return StringStream; }
Sam Clegg49ab5d52017-06-27 20:27:59 +0000135};
136
Heejin Ahn581d2312018-09-05 01:27:38 +0000137int WasmWriter::writeSectionContent(raw_ostream &OS,
Sam Clegg45c215a2018-11-14 18:36:24 +0000138 WasmYAML::DylinkSection &Section) {
139 writeStringRef(Section.Name, OS);
140 encodeULEB128(Section.MemorySize, OS);
141 encodeULEB128(Section.MemoryAlignment, OS);
142 encodeULEB128(Section.TableSize, OS);
143 encodeULEB128(Section.TableAlignment, OS);
Sam Clegg559201d2018-12-12 23:40:58 +0000144 encodeULEB128(Section.Needed.size(), OS);
145 for (StringRef Needed : Section.Needed) {
146 writeStringRef(Needed, OS);
147 }
Sam Clegg45c215a2018-11-14 18:36:24 +0000148 return 0;
149}
150
151int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahn581d2312018-09-05 01:27:38 +0000152 WasmYAML::LinkingSection &Section) {
Sam Clegg49ab5d52017-06-27 20:27:59 +0000153 writeStringRef(Section.Name, OS);
Sam Clegg14598cb2018-04-26 18:15:32 +0000154 encodeULEB128(Section.Version, OS);
Sam Clegg49ab5d52017-06-27 20:27:59 +0000155
156 SubSectionWriter SubSection(OS);
157
Sam Cleggd5784792018-02-23 05:08:34 +0000158 // SYMBOL_TABLE subsection
159 if (Section.SymbolTable.size()) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000160 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg49ab5d52017-06-27 20:27:59 +0000161
Sam Cleggd5784792018-02-23 05:08:34 +0000162 encodeULEB128(Section.SymbolTable.size(), SubSection.GetStream());
Benjamin Kramerf998d9c2018-02-23 12:20:18 +0000163#ifndef NDEBUG
Sam Cleggd5784792018-02-23 05:08:34 +0000164 uint32_t SymbolIndex = 0;
165#endif
166 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
167 assert(Info.Index == SymbolIndex++);
Sam Clegg9f474de2018-03-01 18:06:21 +0000168 writeUint8(SubSection.GetStream(), Info.Kind);
Sam Clegg49ab5d52017-06-27 20:27:59 +0000169 encodeULEB128(Info.Flags, SubSection.GetStream());
Sam Cleggd5784792018-02-23 05:08:34 +0000170 switch (Info.Kind) {
171 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
172 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000173 case wasm::WASM_SYMBOL_TYPE_EVENT:
Sam Cleggd5784792018-02-23 05:08:34 +0000174 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
Hans Wennborg831b2042019-02-12 12:27:08 +0000175 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
176 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Sam Cleggd5784792018-02-23 05:08:34 +0000177 writeStringRef(Info.Name, SubSection.GetStream());
178 break;
179 case wasm::WASM_SYMBOL_TYPE_DATA:
180 writeStringRef(Info.Name, SubSection.GetStream());
181 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
182 encodeULEB128(Info.DataRef.Segment, SubSection.GetStream());
183 encodeULEB128(Info.DataRef.Offset, SubSection.GetStream());
184 encodeULEB128(Info.DataRef.Size, SubSection.GetStream());
185 }
186 break;
Sam Cleggdb159752018-04-26 19:27:28 +0000187 case wasm::WASM_SYMBOL_TYPE_SECTION:
188 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
189 break;
Sam Cleggd5784792018-02-23 05:08:34 +0000190 default:
191 llvm_unreachable("unexpected kind");
192 }
Sam Clegg49ab5d52017-06-27 20:27:59 +0000193 }
194
195 SubSection.Done();
Sam Clegg1e975c12017-06-20 04:04:59 +0000196 }
Sam Clegg81e38242017-09-20 19:03:35 +0000197
198 // SEGMENT_NAMES subsection
Sam Clegge2864172017-09-29 16:50:08 +0000199 if (Section.SegmentInfos.size()) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000200 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Sam Clegge2864172017-09-29 16:50:08 +0000201 encodeULEB128(Section.SegmentInfos.size(), SubSection.GetStream());
202 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Sam Clegge2864172017-09-29 16:50:08 +0000203 writeStringRef(SegmentInfo.Name, SubSection.GetStream());
204 encodeULEB128(SegmentInfo.Alignment, SubSection.GetStream());
205 encodeULEB128(SegmentInfo.Flags, SubSection.GetStream());
Sam Clegg81e38242017-09-20 19:03:35 +0000206 }
207 SubSection.Done();
208 }
Sam Clegge1acb562017-12-14 21:10:03 +0000209
210 // INIT_FUNCS subsection
211 if (Section.InitFunctions.size()) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000212 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Sam Clegge1acb562017-12-14 21:10:03 +0000213 encodeULEB128(Section.InitFunctions.size(), SubSection.GetStream());
214 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
215 encodeULEB128(Func.Priority, SubSection.GetStream());
Sam Cleggd5784792018-02-23 05:08:34 +0000216 encodeULEB128(Func.Symbol, SubSection.GetStream());
Sam Clegge1acb562017-12-14 21:10:03 +0000217 }
218 SubSection.Done();
219 }
Sam Clegge92250a2018-01-09 23:43:14 +0000220
221 // COMDAT_INFO subsection
222 if (Section.Comdats.size()) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000223 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Sam Clegge92250a2018-01-09 23:43:14 +0000224 encodeULEB128(Section.Comdats.size(), SubSection.GetStream());
225 for (const auto &C : Section.Comdats) {
226 writeStringRef(C.Name, SubSection.GetStream());
227 encodeULEB128(0, SubSection.GetStream()); // flags for future use
228 encodeULEB128(C.Entries.size(), SubSection.GetStream());
229 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000230 writeUint8(SubSection.GetStream(), Entry.Kind);
Sam Clegge92250a2018-01-09 23:43:14 +0000231 encodeULEB128(Entry.Index, SubSection.GetStream());
232 }
233 }
234 SubSection.Done();
235 }
236
Sam Clegg1e975c12017-06-20 04:04:59 +0000237 return 0;
238}
239
Heejin Ahn581d2312018-09-05 01:27:38 +0000240int WasmWriter::writeSectionContent(raw_ostream &OS,
241 WasmYAML::NameSection &Section) {
Sam Cleggafe81112017-05-05 18:12:34 +0000242 writeStringRef(Section.Name, OS);
243 if (Section.FunctionNames.size()) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000244 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Cleggafe81112017-05-05 18:12:34 +0000245
Sam Clegg49ab5d52017-06-27 20:27:59 +0000246 SubSectionWriter SubSection(OS);
247
248 encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
Sam Cleggafe81112017-05-05 18:12:34 +0000249 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Sam Clegg49ab5d52017-06-27 20:27:59 +0000250 encodeULEB128(NameEntry.Index, SubSection.GetStream());
251 writeStringRef(NameEntry.Name, SubSection.GetStream());
Sam Cleggafe81112017-05-05 18:12:34 +0000252 }
253
Sam Clegg49ab5d52017-06-27 20:27:59 +0000254 SubSection.Done();
Sam Cleggafe81112017-05-05 18:12:34 +0000255 }
256 return 0;
257}
258
Derek Schuff349a48f2017-03-30 19:44:09 +0000259int WasmWriter::writeSectionContent(raw_ostream &OS,
260 WasmYAML::CustomSection &Section) {
Sam Clegg45c215a2018-11-14 18:36:24 +0000261 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
262 if (auto Err = writeSectionContent(OS, *S))
263 return Err;
264 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
Sam Clegg1e975c12017-06-20 04:04:59 +0000265 if (auto Err = writeSectionContent(OS, *S))
266 return Err;
267 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
268 if (auto Err = writeSectionContent(OS, *S))
269 return Err;
Sam Cleggafe81112017-05-05 18:12:34 +0000270 } else {
Sam Cleggb068ce92018-04-12 20:31:12 +0000271 writeStringRef(Section.Name, OS);
Sam Cleggafe81112017-05-05 18:12:34 +0000272 Section.Payload.writeAsBinary(OS);
273 }
Derek Schuff349a48f2017-03-30 19:44:09 +0000274 return 0;
275}
276
277int WasmWriter::writeSectionContent(raw_ostream &OS,
278 WasmYAML::TypeSection &Section) {
279 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegg6b54fc32018-01-09 21:38:53 +0000280 uint32_t ExpectedIndex = 0;
Sam Cleggafe81112017-05-05 18:12:34 +0000281 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegg6b54fc32018-01-09 21:38:53 +0000282 if (Sig.Index != ExpectedIndex) {
283 errs() << "Unexpected type index: " << Sig.Index << "\n";
284 return 1;
285 }
286 ++ExpectedIndex;
Sam Clegg9f474de2018-03-01 18:06:21 +0000287 writeUint8(OS, Sig.Form);
Derek Schuff349a48f2017-03-30 19:44:09 +0000288 encodeULEB128(Sig.ParamTypes.size(), OS);
289 for (auto ParamType : Sig.ParamTypes)
Sam Clegg9f474de2018-03-01 18:06:21 +0000290 writeUint8(OS, ParamType);
Derek Schuff349a48f2017-03-30 19:44:09 +0000291 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000292 encodeULEB128(0, OS);
Derek Schuff349a48f2017-03-30 19:44:09 +0000293 } else {
294 encodeULEB128(1, OS);
Sam Clegg9f474de2018-03-01 18:06:21 +0000295 writeUint8(OS, Sig.ReturnType);
Derek Schuff349a48f2017-03-30 19:44:09 +0000296 }
297 }
298 return 0;
299}
300
301int WasmWriter::writeSectionContent(raw_ostream &OS,
302 WasmYAML::ImportSection &Section) {
303 encodeULEB128(Section.Imports.size(), OS);
Sam Cleggafe81112017-05-05 18:12:34 +0000304 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000305 writeStringRef(Import.Module, OS);
306 writeStringRef(Import.Field, OS);
Sam Clegg9f474de2018-03-01 18:06:21 +0000307 writeUint8(OS, Import.Kind);
Derek Schuff349a48f2017-03-30 19:44:09 +0000308 switch (Import.Kind) {
309 case wasm::WASM_EXTERNAL_FUNCTION:
310 encodeULEB128(Import.SigIndex, OS);
Sam Clegg6b54fc32018-01-09 21:38:53 +0000311 NumImportedFunctions++;
Derek Schuff349a48f2017-03-30 19:44:09 +0000312 break;
313 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg9f474de2018-03-01 18:06:21 +0000314 writeUint8(OS, Import.GlobalImport.Type);
Sam Cleggbde17ff2017-05-10 00:14:04 +0000315 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegg6b54fc32018-01-09 21:38:53 +0000316 NumImportedGlobals++;
Sam Clegg65e284e2017-05-09 23:48:41 +0000317 break;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000318 case wasm::WASM_EXTERNAL_EVENT:
319 writeUint32(OS, Import.EventImport.Attribute);
320 writeUint32(OS, Import.EventImport.SigIndex);
321 NumImportedGlobals++;
322 break;
Sam Clegg65e284e2017-05-09 23:48:41 +0000323 case wasm::WASM_EXTERNAL_MEMORY:
324 writeLimits(Import.Memory, OS);
325 break;
326 case wasm::WASM_EXTERNAL_TABLE:
Heejin Ahn581d2312018-09-05 01:27:38 +0000327 writeUint8(OS, Import.TableImport.ElemType);
Sam Cleggbde17ff2017-05-10 00:14:04 +0000328 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuff349a48f2017-03-30 19:44:09 +0000329 break;
330 default:
Sam Clegg6b54fc32018-01-09 21:38:53 +0000331 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuff349a48f2017-03-30 19:44:09 +0000332 return 1;
333 }
334 }
335 return 0;
336}
337
338int WasmWriter::writeSectionContent(raw_ostream &OS,
339 WasmYAML::FunctionSection &Section) {
340 encodeULEB128(Section.FunctionTypes.size(), OS);
341 for (uint32_t FuncType : Section.FunctionTypes) {
342 encodeULEB128(FuncType, OS);
343 }
344 return 0;
345}
346
347int WasmWriter::writeSectionContent(raw_ostream &OS,
348 WasmYAML::ExportSection &Section) {
349 encodeULEB128(Section.Exports.size(), OS);
Sam Cleggafe81112017-05-05 18:12:34 +0000350 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000351 writeStringRef(Export.Name, OS);
Sam Clegg9f474de2018-03-01 18:06:21 +0000352 writeUint8(OS, Export.Kind);
Derek Schuff349a48f2017-03-30 19:44:09 +0000353 encodeULEB128(Export.Index, OS);
354 }
355 return 0;
356}
357
358int WasmWriter::writeSectionContent(raw_ostream &OS,
359 WasmYAML::StartSection &Section) {
360 encodeULEB128(Section.StartFunction, OS);
361 return 0;
362}
363
364int WasmWriter::writeSectionContent(raw_ostream &OS,
365 WasmYAML::TableSection &Section) {
366 encodeULEB128(Section.Tables.size(), OS);
367 for (auto &Table : Section.Tables) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000368 writeUint8(OS, Table.ElemType);
Derek Schuff349a48f2017-03-30 19:44:09 +0000369 writeLimits(Table.TableLimits, OS);
370 }
371 return 0;
372}
373
374int WasmWriter::writeSectionContent(raw_ostream &OS,
375 WasmYAML::MemorySection &Section) {
376 encodeULEB128(Section.Memories.size(), OS);
Sam Cleggafe81112017-05-05 18:12:34 +0000377 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000378 writeLimits(Mem, OS);
379 }
380 return 0;
381}
382
383int WasmWriter::writeSectionContent(raw_ostream &OS,
384 WasmYAML::GlobalSection &Section) {
385 encodeULEB128(Section.Globals.size(), OS);
Sam Clegg6b54fc32018-01-09 21:38:53 +0000386 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuff349a48f2017-03-30 19:44:09 +0000387 for (auto &Global : Section.Globals) {
Sam Clegg6b54fc32018-01-09 21:38:53 +0000388 if (Global.Index != ExpectedIndex) {
389 errs() << "Unexpected global index: " << Global.Index << "\n";
390 return 1;
391 }
392 ++ExpectedIndex;
Sam Clegg9f474de2018-03-01 18:06:21 +0000393 writeUint8(OS, Global.Type);
Derek Schuff349a48f2017-03-30 19:44:09 +0000394 writeUint8(OS, Global.Mutable);
395 writeInitExpr(Global.InitExpr, OS);
396 }
397 return 0;
398}
399
400int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000401 WasmYAML::EventSection &Section) {
402 encodeULEB128(Section.Events.size(), OS);
403 uint32_t ExpectedIndex = NumImportedEvents;
404 for (auto &Event : Section.Events) {
405 if (Event.Index != ExpectedIndex) {
406 errs() << "Unexpected event index: " << Event.Index << "\n";
407 return 1;
408 }
409 ++ExpectedIndex;
410 encodeULEB128(Event.Attribute, OS);
411 encodeULEB128(Event.SigIndex, OS);
412 }
413 return 0;
414}
415
416int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuff349a48f2017-03-30 19:44:09 +0000417 WasmYAML::ElemSection &Section) {
418 encodeULEB128(Section.Segments.size(), OS);
419 for (auto &Segment : Section.Segments) {
420 encodeULEB128(Segment.TableIndex, OS);
421 writeInitExpr(Segment.Offset, OS);
422
423 encodeULEB128(Segment.Functions.size(), OS);
424 for (auto &Function : Segment.Functions) {
425 encodeULEB128(Function, OS);
426 }
427 }
428 return 0;
429}
430
431int WasmWriter::writeSectionContent(raw_ostream &OS,
432 WasmYAML::CodeSection &Section) {
433 encodeULEB128(Section.Functions.size(), OS);
Sam Clegg6b54fc32018-01-09 21:38:53 +0000434 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuff349a48f2017-03-30 19:44:09 +0000435 for (auto &Func : Section.Functions) {
436 std::string OutString;
437 raw_string_ostream StringStream(OutString);
Sam Clegg6b54fc32018-01-09 21:38:53 +0000438 if (Func.Index != ExpectedIndex) {
439 errs() << "Unexpected function index: " << Func.Index << "\n";
440 return 1;
441 }
442 ++ExpectedIndex;
Derek Schuff349a48f2017-03-30 19:44:09 +0000443
444 encodeULEB128(Func.Locals.size(), StringStream);
445 for (auto &LocalDecl : Func.Locals) {
446 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg9f474de2018-03-01 18:06:21 +0000447 writeUint8(StringStream, LocalDecl.Type);
Derek Schuff349a48f2017-03-30 19:44:09 +0000448 }
449
450 Func.Body.writeAsBinary(StringStream);
451
452 // Write the section size followed by the content
453 StringStream.flush();
454 encodeULEB128(OutString.size(), OS);
455 OS << OutString;
456 }
457 return 0;
458}
459
460int WasmWriter::writeSectionContent(raw_ostream &OS,
461 WasmYAML::DataSection &Section) {
462 encodeULEB128(Section.Segments.size(), OS);
463 for (auto &Segment : Section.Segments) {
Sam Cleggc9c28d92017-07-12 00:24:54 +0000464 encodeULEB128(Segment.MemoryIndex, OS);
Derek Schuff349a48f2017-03-30 19:44:09 +0000465 writeInitExpr(Segment.Offset, OS);
466 encodeULEB128(Segment.Content.binary_size(), OS);
467 Segment.Content.writeAsBinary(OS);
468 }
469 return 0;
470}
471
Sam Clegg194a4e02018-04-24 18:11:36 +0000472int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
473 uint32_t SectionIndex) {
Derek Schuff349a48f2017-03-30 19:44:09 +0000474 switch (Sec.Type) {
Heejin Ahn581d2312018-09-05 01:27:38 +0000475 case wasm::WASM_SEC_CODE:
476 writeStringRef("reloc.CODE", OS);
477 break;
478 case wasm::WASM_SEC_DATA:
479 writeStringRef("reloc.DATA", OS);
480 break;
481 case wasm::WASM_SEC_CUSTOM: {
482 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
483 if (!CustomSection->Name.startswith(".debug_")) {
484 llvm_unreachable("not yet implemented (only for debug sections)");
Derek Schuff349a48f2017-03-30 19:44:09 +0000485 return 1;
Heejin Ahn581d2312018-09-05 01:27:38 +0000486 }
487
488 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
489 break;
490 }
491 default:
492 llvm_unreachable("not yet implemented");
493 return 1;
Derek Schuff349a48f2017-03-30 19:44:09 +0000494 }
495
Sam Clegg194a4e02018-04-24 18:11:36 +0000496 encodeULEB128(SectionIndex, OS);
Derek Schuff349a48f2017-03-30 19:44:09 +0000497 encodeULEB128(Sec.Relocations.size(), OS);
498
Heejin Ahn581d2312018-09-05 01:27:38 +0000499 for (auto Reloc : Sec.Relocations) {
Sam Clegg9f474de2018-03-01 18:06:21 +0000500 writeUint8(OS, Reloc.Type);
Derek Schuff349a48f2017-03-30 19:44:09 +0000501 encodeULEB128(Reloc.Offset, OS);
502 encodeULEB128(Reloc.Index, OS);
503 switch (Reloc.Type) {
Heejin Ahn581d2312018-09-05 01:27:38 +0000504 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
505 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
506 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
507 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
508 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
509 encodeULEB128(Reloc.Addend, OS);
Derek Schuff349a48f2017-03-30 19:44:09 +0000510 }
511 }
512 return 0;
513}
514
Derek Schuff349a48f2017-03-30 19:44:09 +0000515int WasmWriter::writeWasm(raw_ostream &OS) {
516 // Write headers
517 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
518 writeUint32(OS, Obj.Header.Version);
519
520 // Write each section
Heejin Ahne2f3e502018-12-15 00:58:12 +0000521 llvm::object::WasmSectionOrderChecker Checker;
Derek Schuff349a48f2017-03-30 19:44:09 +0000522 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Heejin Ahne2f3e502018-12-15 00:58:12 +0000523 StringRef SecName = "";
524 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
525 SecName = S->Name;
526 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
527 errs() << "Out of order section type: " << Sec->Type << "\n";
528 return 1;
529 }
Sam Clegg6b54fc32018-01-09 21:38:53 +0000530 encodeULEB128(Sec->Type, OS);
Derek Schuff349a48f2017-03-30 19:44:09 +0000531 std::string OutString;
532 raw_string_ostream StringStream(OutString);
533 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
534 if (auto Err = writeSectionContent(StringStream, *S))
535 return Err;
536 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
537 if (auto Err = writeSectionContent(StringStream, *S))
538 return Err;
539 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
540 if (auto Err = writeSectionContent(StringStream, *S))
541 return Err;
542 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
543 if (auto Err = writeSectionContent(StringStream, *S))
544 return Err;
545 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
546 if (auto Err = writeSectionContent(StringStream, *S))
547 return Err;
548 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
549 if (auto Err = writeSectionContent(StringStream, *S))
550 return Err;
551 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
552 if (auto Err = writeSectionContent(StringStream, *S))
553 return Err;
Heejin Ahn8bcdd042018-11-14 02:46:21 +0000554 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
555 if (auto Err = writeSectionContent(StringStream, *S))
556 return Err;
Derek Schuff349a48f2017-03-30 19:44:09 +0000557 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
558 if (auto Err = writeSectionContent(StringStream, *S))
559 return Err;
560 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
561 if (auto Err = writeSectionContent(StringStream, *S))
562 return Err;
563 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
564 if (auto Err = writeSectionContent(StringStream, *S))
565 return Err;
566 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
567 if (auto Err = writeSectionContent(StringStream, *S))
568 return Err;
569 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
570 if (auto Err = writeSectionContent(StringStream, *S))
571 return Err;
572 } else {
573 errs() << "Unknown section type: " << Sec->Type << "\n";
574 return 1;
575 }
576 StringStream.flush();
577
578 // Write the section size followed by the content
579 encodeULEB128(OutString.size(), OS);
580 OS << OutString;
581 }
582
583 // write reloc sections for any section that have relocations
Sam Clegg194a4e02018-04-24 18:11:36 +0000584 uint32_t SectionIndex = 0;
Derek Schuff349a48f2017-03-30 19:44:09 +0000585 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg194a4e02018-04-24 18:11:36 +0000586 if (Sec->Relocations.empty()) {
587 SectionIndex++;
Derek Schuff349a48f2017-03-30 19:44:09 +0000588 continue;
Sam Clegg194a4e02018-04-24 18:11:36 +0000589 }
Derek Schuff349a48f2017-03-30 19:44:09 +0000590
Sam Clegg9f474de2018-03-01 18:06:21 +0000591 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuff349a48f2017-03-30 19:44:09 +0000592 std::string OutString;
593 raw_string_ostream StringStream(OutString);
Sam Clegg194a4e02018-04-24 18:11:36 +0000594 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuff349a48f2017-03-30 19:44:09 +0000595 StringStream.flush();
596
597 encodeULEB128(OutString.size(), OS);
598 OS << OutString;
599 }
600
601 return 0;
602}
603
604int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
605 WasmWriter Writer(Doc);
606
607 return Writer.writeWasm(Out);
608}