blob: 242bc6b6442a2b71f38258648e6a9916d06a0c47 [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
Heejin Ahnfeef7202018-12-15 00:58:12 +000016#include "llvm/Object/Wasm.h"
Derek Schuffd3d84fd2017-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 Cleggb7787fd2017-06-20 04:04:59 +000029
30private:
Sam Clegg6f08c842018-04-24 18:11:36 +000031 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
32 uint32_t SectionIndex);
Sam Clegg03cdd122017-05-05 18:12:34 +000033
Derek Schuffd3d84fd2017-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 Ahnda419bd2018-11-14 02:46:21 +000041 int writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
Derek Schuffd3d84fd2017-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 Cleggb7787fd2017-06-20 04:04:59 +000048 // Custom section types
Sam Clegge4afbc62018-11-14 18:36:24 +000049 int writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
Sam Cleggb7787fd2017-06-20 04:04:59 +000050 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
51 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
Thomas Livelycbda16e2019-01-17 02:29:55 +000052 int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000053 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000054 uint32_t NumImportedFunctions = 0;
55 uint32_t NumImportedGlobals = 0;
Heejin Ahnda419bd2018-11-14 02:46:21 +000056 uint32_t NumImportedEvents = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +000057};
58
59static int writeUint64(raw_ostream &OS, uint64_t Value) {
60 char Data[sizeof(Value)];
61 support::endian::write64le(Data, Value);
62 OS.write(Data, sizeof(Data));
63 return 0;
64}
65
66static int writeUint32(raw_ostream &OS, uint32_t Value) {
67 char Data[sizeof(Value)];
68 support::endian::write32le(Data, Value);
69 OS.write(Data, sizeof(Data));
70 return 0;
71}
72
73static int writeUint8(raw_ostream &OS, uint8_t Value) {
74 char Data[sizeof(Value)];
75 memcpy(Data, &Value, sizeof(Data));
76 OS.write(Data, sizeof(Data));
77 return 0;
78}
79
Sam Clegg03cdd122017-05-05 18:12:34 +000080static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000081 encodeULEB128(Str.size(), OS);
82 OS << Str;
83 return 0;
84}
85
Sam Clegg03cdd122017-05-05 18:12:34 +000086static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +000087 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000088 encodeULEB128(Lim.Initial, OS);
89 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
90 encodeULEB128(Lim.Maximum, OS);
91 return 0;
92}
93
Sam Clegg03cdd122017-05-05 18:12:34 +000094static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000095 writeUint8(OS, InitExpr.Opcode);
96 switch (InitExpr.Opcode) {
97 case wasm::WASM_OPCODE_I32_CONST:
98 encodeSLEB128(InitExpr.Value.Int32, OS);
99 break;
100 case wasm::WASM_OPCODE_I64_CONST:
101 encodeSLEB128(InitExpr.Value.Int64, OS);
102 break;
103 case wasm::WASM_OPCODE_F32_CONST:
104 writeUint32(OS, InitExpr.Value.Float32);
105 break;
106 case wasm::WASM_OPCODE_F64_CONST:
107 writeUint64(OS, InitExpr.Value.Float64);
108 break;
Thomas Lively6a87dda2019-01-08 06:25:55 +0000109 case wasm::WASM_OPCODE_GLOBAL_GET:
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000110 encodeULEB128(InitExpr.Value.Global, OS);
111 break;
112 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000113 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000114 return 1;
115 }
116 writeUint8(OS, wasm::WASM_OPCODE_END);
117 return 0;
118}
119
Sam Clegg9e1ade92017-06-27 20:27:59 +0000120class SubSectionWriter {
121 raw_ostream &OS;
122 std::string OutString;
123 raw_string_ostream StringStream;
Sam Cleggb7787fd2017-06-20 04:04:59 +0000124
Sam Clegg9e1ade92017-06-27 20:27:59 +0000125public:
126 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Cleggb7787fd2017-06-20 04:04:59 +0000127
Sam Clegg9e1ade92017-06-27 20:27:59 +0000128 void Done() {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000129 StringStream.flush();
130 encodeULEB128(OutString.size(), OS);
131 OS << OutString;
Sam Clegg9e1ade92017-06-27 20:27:59 +0000132 OutString.clear();
133 }
134
Heejin Ahnf208f632018-09-05 01:27:38 +0000135 raw_ostream &GetStream() { return StringStream; }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000136};
137
Heejin Ahnf208f632018-09-05 01:27:38 +0000138int WasmWriter::writeSectionContent(raw_ostream &OS,
Sam Clegge4afbc62018-11-14 18:36:24 +0000139 WasmYAML::DylinkSection &Section) {
140 writeStringRef(Section.Name, OS);
141 encodeULEB128(Section.MemorySize, OS);
142 encodeULEB128(Section.MemoryAlignment, OS);
143 encodeULEB128(Section.TableSize, OS);
144 encodeULEB128(Section.TableAlignment, OS);
Sam Clegg03801252018-12-12 23:40:58 +0000145 encodeULEB128(Section.Needed.size(), OS);
146 for (StringRef Needed : Section.Needed) {
147 writeStringRef(Needed, OS);
148 }
Sam Clegge4afbc62018-11-14 18:36:24 +0000149 return 0;
150}
151
152int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnf208f632018-09-05 01:27:38 +0000153 WasmYAML::LinkingSection &Section) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000154 writeStringRef(Section.Name, OS);
Sam Clegg6bb5a412018-04-26 18:15:32 +0000155 encodeULEB128(Section.Version, OS);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000156
157 SubSectionWriter SubSection(OS);
158
Sam Clegg6c899ba2018-02-23 05:08:34 +0000159 // SYMBOL_TABLE subsection
160 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000161 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000162
Sam Clegg6c899ba2018-02-23 05:08:34 +0000163 encodeULEB128(Section.SymbolTable.size(), SubSection.GetStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000164#ifndef NDEBUG
Sam Clegg6c899ba2018-02-23 05:08:34 +0000165 uint32_t SymbolIndex = 0;
166#endif
167 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
168 assert(Info.Index == SymbolIndex++);
Sam Clegg03e101f2018-03-01 18:06:21 +0000169 writeUint8(SubSection.GetStream(), Info.Kind);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000170 encodeULEB128(Info.Flags, SubSection.GetStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000171 switch (Info.Kind) {
172 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
173 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahnda419bd2018-11-14 02:46:21 +0000174 case wasm::WASM_SYMBOL_TYPE_EVENT:
Sam Clegg6c899ba2018-02-23 05:08:34 +0000175 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
176 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
177 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 Clegg6a31a0d2018-04-26 19:27:28 +0000187 case wasm::WASM_SYMBOL_TYPE_SECTION:
188 encodeULEB128(Info.ElementIndex, SubSection.GetStream());
189 break;
Sam Clegg6c899ba2018-02-23 05:08:34 +0000190 default:
191 llvm_unreachable("unexpected kind");
192 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000193 }
194
195 SubSection.Done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000196 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000197
198 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000199 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000200 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Sam Clegg63ebb812017-09-29 16:50:08 +0000201 encodeULEB128(Section.SegmentInfos.size(), SubSection.GetStream());
202 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Sam Clegg63ebb812017-09-29 16:50:08 +0000203 writeStringRef(SegmentInfo.Name, SubSection.GetStream());
204 encodeULEB128(SegmentInfo.Alignment, SubSection.GetStream());
205 encodeULEB128(SegmentInfo.Flags, SubSection.GetStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000206 }
207 SubSection.Done();
208 }
Sam Clegg42739982017-12-14 21:10:03 +0000209
210 // INIT_FUNCS subsection
211 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000212 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Sam Clegg42739982017-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 Clegg6c899ba2018-02-23 05:08:34 +0000216 encodeULEB128(Func.Symbol, SubSection.GetStream());
Sam Clegg42739982017-12-14 21:10:03 +0000217 }
218 SubSection.Done();
219 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000220
221 // COMDAT_INFO subsection
222 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000223 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Sam Cleggea7cace2018-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 Clegg03e101f2018-03-01 18:06:21 +0000230 writeUint8(SubSection.GetStream(), Entry.Kind);
Sam Cleggea7cace2018-01-09 23:43:14 +0000231 encodeULEB128(Entry.Index, SubSection.GetStream());
232 }
233 }
234 SubSection.Done();
235 }
236
Sam Cleggb7787fd2017-06-20 04:04:59 +0000237 return 0;
238}
239
Heejin Ahnf208f632018-09-05 01:27:38 +0000240int WasmWriter::writeSectionContent(raw_ostream &OS,
241 WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000242 writeStringRef(Section.Name, OS);
243 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000244 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000245
Sam Clegg9e1ade92017-06-27 20:27:59 +0000246 SubSectionWriter SubSection(OS);
247
248 encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000249 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000250 encodeULEB128(NameEntry.Index, SubSection.GetStream());
251 writeStringRef(NameEntry.Name, SubSection.GetStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000252 }
253
Sam Clegg9e1ade92017-06-27 20:27:59 +0000254 SubSection.Done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000255 }
256 return 0;
257}
258
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000259int WasmWriter::writeSectionContent(raw_ostream &OS,
Thomas Livelycbda16e2019-01-17 02:29:55 +0000260 WasmYAML::ProducersSection &Section) {
261 writeStringRef(Section.Name, OS);
262 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
263 int(!Section.SDKs.empty());
264 if (Fields == 0)
265 return 0;
266 encodeULEB128(Fields, OS);
267 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
268 std::make_pair(StringRef("processed-by"), &Section.Tools),
269 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
270 if (Field.second->empty())
271 continue;
272 writeStringRef(Field.first, OS);
273 encodeULEB128(Field.second->size(), OS);
274 for (auto &Entry : *Field.second) {
275 writeStringRef(Entry.Name, OS);
276 writeStringRef(Entry.Version, OS);
277 }
278 }
279 return 0;
280}
281
282int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000283 WasmYAML::CustomSection &Section) {
Sam Clegge4afbc62018-11-14 18:36:24 +0000284 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
285 if (auto Err = writeSectionContent(OS, *S))
286 return Err;
287 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000288 if (auto Err = writeSectionContent(OS, *S))
289 return Err;
290 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
291 if (auto Err = writeSectionContent(OS, *S))
292 return Err;
Thomas Livelycbda16e2019-01-17 02:29:55 +0000293 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
294 if (auto Err = writeSectionContent(OS, *S))
295 return Err;
Sam Clegg03cdd122017-05-05 18:12:34 +0000296 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000297 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000298 Section.Payload.writeAsBinary(OS);
299 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000300 return 0;
301}
302
303int WasmWriter::writeSectionContent(raw_ostream &OS,
304 WasmYAML::TypeSection &Section) {
305 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000306 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000307 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000308 if (Sig.Index != ExpectedIndex) {
309 errs() << "Unexpected type index: " << Sig.Index << "\n";
310 return 1;
311 }
312 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000313 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000314 encodeULEB128(Sig.ParamTypes.size(), OS);
315 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000316 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000317 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000318 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000319 } else {
320 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000321 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000322 }
323 }
324 return 0;
325}
326
327int WasmWriter::writeSectionContent(raw_ostream &OS,
328 WasmYAML::ImportSection &Section) {
329 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000330 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000331 writeStringRef(Import.Module, OS);
332 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000333 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000334 switch (Import.Kind) {
335 case wasm::WASM_EXTERNAL_FUNCTION:
336 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000337 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000338 break;
339 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000340 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000341 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000342 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000343 break;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000344 case wasm::WASM_EXTERNAL_EVENT:
345 writeUint32(OS, Import.EventImport.Attribute);
346 writeUint32(OS, Import.EventImport.SigIndex);
347 NumImportedGlobals++;
348 break;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000349 case wasm::WASM_EXTERNAL_MEMORY:
350 writeLimits(Import.Memory, OS);
351 break;
352 case wasm::WASM_EXTERNAL_TABLE:
Heejin Ahnf208f632018-09-05 01:27:38 +0000353 writeUint8(OS, Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000354 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000355 break;
356 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000357 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000358 return 1;
359 }
360 }
361 return 0;
362}
363
364int WasmWriter::writeSectionContent(raw_ostream &OS,
365 WasmYAML::FunctionSection &Section) {
366 encodeULEB128(Section.FunctionTypes.size(), OS);
367 for (uint32_t FuncType : Section.FunctionTypes) {
368 encodeULEB128(FuncType, OS);
369 }
370 return 0;
371}
372
373int WasmWriter::writeSectionContent(raw_ostream &OS,
374 WasmYAML::ExportSection &Section) {
375 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000376 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000377 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000378 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000379 encodeULEB128(Export.Index, OS);
380 }
381 return 0;
382}
383
384int WasmWriter::writeSectionContent(raw_ostream &OS,
385 WasmYAML::StartSection &Section) {
386 encodeULEB128(Section.StartFunction, OS);
387 return 0;
388}
389
390int WasmWriter::writeSectionContent(raw_ostream &OS,
391 WasmYAML::TableSection &Section) {
392 encodeULEB128(Section.Tables.size(), OS);
393 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000394 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000395 writeLimits(Table.TableLimits, OS);
396 }
397 return 0;
398}
399
400int WasmWriter::writeSectionContent(raw_ostream &OS,
401 WasmYAML::MemorySection &Section) {
402 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000403 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000404 writeLimits(Mem, OS);
405 }
406 return 0;
407}
408
409int WasmWriter::writeSectionContent(raw_ostream &OS,
410 WasmYAML::GlobalSection &Section) {
411 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000412 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000413 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000414 if (Global.Index != ExpectedIndex) {
415 errs() << "Unexpected global index: " << Global.Index << "\n";
416 return 1;
417 }
418 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000419 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000420 writeUint8(OS, Global.Mutable);
421 writeInitExpr(Global.InitExpr, OS);
422 }
423 return 0;
424}
425
426int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnda419bd2018-11-14 02:46:21 +0000427 WasmYAML::EventSection &Section) {
428 encodeULEB128(Section.Events.size(), OS);
429 uint32_t ExpectedIndex = NumImportedEvents;
430 for (auto &Event : Section.Events) {
431 if (Event.Index != ExpectedIndex) {
432 errs() << "Unexpected event index: " << Event.Index << "\n";
433 return 1;
434 }
435 ++ExpectedIndex;
436 encodeULEB128(Event.Attribute, OS);
437 encodeULEB128(Event.SigIndex, OS);
438 }
439 return 0;
440}
441
442int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000443 WasmYAML::ElemSection &Section) {
444 encodeULEB128(Section.Segments.size(), OS);
445 for (auto &Segment : Section.Segments) {
446 encodeULEB128(Segment.TableIndex, OS);
447 writeInitExpr(Segment.Offset, OS);
448
449 encodeULEB128(Segment.Functions.size(), OS);
450 for (auto &Function : Segment.Functions) {
451 encodeULEB128(Function, OS);
452 }
453 }
454 return 0;
455}
456
457int WasmWriter::writeSectionContent(raw_ostream &OS,
458 WasmYAML::CodeSection &Section) {
459 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000460 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000461 for (auto &Func : Section.Functions) {
462 std::string OutString;
463 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000464 if (Func.Index != ExpectedIndex) {
465 errs() << "Unexpected function index: " << Func.Index << "\n";
466 return 1;
467 }
468 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000469
470 encodeULEB128(Func.Locals.size(), StringStream);
471 for (auto &LocalDecl : Func.Locals) {
472 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000473 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000474 }
475
476 Func.Body.writeAsBinary(StringStream);
477
478 // Write the section size followed by the content
479 StringStream.flush();
480 encodeULEB128(OutString.size(), OS);
481 OS << OutString;
482 }
483 return 0;
484}
485
486int WasmWriter::writeSectionContent(raw_ostream &OS,
487 WasmYAML::DataSection &Section) {
488 encodeULEB128(Section.Segments.size(), OS);
489 for (auto &Segment : Section.Segments) {
Sam Clegg9c07f942017-07-12 00:24:54 +0000490 encodeULEB128(Segment.MemoryIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000491 writeInitExpr(Segment.Offset, OS);
492 encodeULEB128(Segment.Content.binary_size(), OS);
493 Segment.Content.writeAsBinary(OS);
494 }
495 return 0;
496}
497
Sam Clegg6f08c842018-04-24 18:11:36 +0000498int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
499 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000500 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000501 case wasm::WASM_SEC_CODE:
502 writeStringRef("reloc.CODE", OS);
503 break;
504 case wasm::WASM_SEC_DATA:
505 writeStringRef("reloc.DATA", OS);
506 break;
507 case wasm::WASM_SEC_CUSTOM: {
508 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
509 if (!CustomSection->Name.startswith(".debug_")) {
510 llvm_unreachable("not yet implemented (only for debug sections)");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000511 return 1;
Heejin Ahnf208f632018-09-05 01:27:38 +0000512 }
513
514 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
515 break;
516 }
517 default:
518 llvm_unreachable("not yet implemented");
519 return 1;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000520 }
521
Sam Clegg6f08c842018-04-24 18:11:36 +0000522 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000523 encodeULEB128(Sec.Relocations.size(), OS);
524
Heejin Ahnf208f632018-09-05 01:27:38 +0000525 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000526 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000527 encodeULEB128(Reloc.Offset, OS);
528 encodeULEB128(Reloc.Index, OS);
529 switch (Reloc.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000530 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
531 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
532 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
533 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
534 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
535 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000536 }
537 }
538 return 0;
539}
540
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000541int WasmWriter::writeWasm(raw_ostream &OS) {
542 // Write headers
543 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
544 writeUint32(OS, Obj.Header.Version);
545
546 // Write each section
Heejin Ahnfeef7202018-12-15 00:58:12 +0000547 llvm::object::WasmSectionOrderChecker Checker;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000548 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Heejin Ahnfeef7202018-12-15 00:58:12 +0000549 StringRef SecName = "";
550 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
551 SecName = S->Name;
552 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
553 errs() << "Out of order section type: " << Sec->Type << "\n";
554 return 1;
555 }
Sam Clegge53af7f2018-01-09 21:38:53 +0000556 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000557 std::string OutString;
558 raw_string_ostream StringStream(OutString);
559 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
560 if (auto Err = writeSectionContent(StringStream, *S))
561 return Err;
562 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
563 if (auto Err = writeSectionContent(StringStream, *S))
564 return Err;
565 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
566 if (auto Err = writeSectionContent(StringStream, *S))
567 return Err;
568 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
569 if (auto Err = writeSectionContent(StringStream, *S))
570 return Err;
571 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
572 if (auto Err = writeSectionContent(StringStream, *S))
573 return Err;
574 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
575 if (auto Err = writeSectionContent(StringStream, *S))
576 return Err;
577 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
578 if (auto Err = writeSectionContent(StringStream, *S))
579 return Err;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000580 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
581 if (auto Err = writeSectionContent(StringStream, *S))
582 return Err;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000583 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
584 if (auto Err = writeSectionContent(StringStream, *S))
585 return Err;
586 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
587 if (auto Err = writeSectionContent(StringStream, *S))
588 return Err;
589 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
590 if (auto Err = writeSectionContent(StringStream, *S))
591 return Err;
592 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
593 if (auto Err = writeSectionContent(StringStream, *S))
594 return Err;
595 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
596 if (auto Err = writeSectionContent(StringStream, *S))
597 return Err;
598 } else {
599 errs() << "Unknown section type: " << Sec->Type << "\n";
600 return 1;
601 }
602 StringStream.flush();
603
604 // Write the section size followed by the content
605 encodeULEB128(OutString.size(), OS);
606 OS << OutString;
607 }
608
609 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000610 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000611 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000612 if (Sec->Relocations.empty()) {
613 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000614 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000615 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000616
Sam Clegg03e101f2018-03-01 18:06:21 +0000617 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000618 std::string OutString;
619 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000620 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000621 StringStream.flush();
622
623 encodeULEB128(OutString.size(), OS);
624 OS << OutString;
625 }
626
627 return 0;
628}
629
630int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
631 WasmWriter Writer(Doc);
632
633 return Writer.writeWasm(Out);
634}