blob: fcbcb8a40d5c535c80af0e2a7371c1f2b3279d00 [file] [log] [blame]
Derek Schuffd3d84fd2017-03-30 19:44:09 +00001//===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Derek Schuffd3d84fd2017-03-30 19:44:09 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000010/// The Wasm component of yaml2obj.
Derek Schuffd3d84fd2017-03-30 19:44:09 +000011///
12//===----------------------------------------------------------------------===//
13//
Sam Clegg6c899ba2018-02-23 05:08:34 +000014
Heejin Ahnfeef7202018-12-15 00:58:12 +000015#include "llvm/Object/Wasm.h"
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);
Thomas Livelycbda16e2019-01-17 02:29:55 +000051 int writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000052 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000053 uint32_t NumImportedFunctions = 0;
54 uint32_t NumImportedGlobals = 0;
Heejin Ahnda419bd2018-11-14 02:46:21 +000055 uint32_t NumImportedEvents = 0;
Derek Schuffd3d84fd2017-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 Clegg03cdd122017-05-05 18:12:34 +000079static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000080 encodeULEB128(Str.size(), OS);
81 OS << Str;
82 return 0;
83}
84
Sam Clegg03cdd122017-05-05 18:12:34 +000085static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +000086 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-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 Clegg03cdd122017-05-05 18:12:34 +000093static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuffd3d84fd2017-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 Lively6a87dda2019-01-08 06:25:55 +0000108 case wasm::WASM_OPCODE_GLOBAL_GET:
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000109 encodeULEB128(InitExpr.Value.Global, OS);
110 break;
111 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000112 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000113 return 1;
114 }
115 writeUint8(OS, wasm::WASM_OPCODE_END);
116 return 0;
117}
118
Sam Clegg9e1ade92017-06-27 20:27:59 +0000119class SubSectionWriter {
120 raw_ostream &OS;
121 std::string OutString;
122 raw_string_ostream StringStream;
Sam Cleggb7787fd2017-06-20 04:04:59 +0000123
Sam Clegg9e1ade92017-06-27 20:27:59 +0000124public:
125 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Cleggb7787fd2017-06-20 04:04:59 +0000126
Heejin Ahn18c56a02019-02-04 19:13:39 +0000127 void done() {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000128 StringStream.flush();
129 encodeULEB128(OutString.size(), OS);
130 OS << OutString;
Sam Clegg9e1ade92017-06-27 20:27:59 +0000131 OutString.clear();
132 }
133
Heejin Ahn18c56a02019-02-04 19:13:39 +0000134 raw_ostream &getStream() { return StringStream; }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000135};
136
Heejin Ahnf208f632018-09-05 01:27:38 +0000137int WasmWriter::writeSectionContent(raw_ostream &OS,
Sam Clegge4afbc62018-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 Clegg03801252018-12-12 23:40:58 +0000144 encodeULEB128(Section.Needed.size(), OS);
145 for (StringRef Needed : Section.Needed) {
146 writeStringRef(Needed, OS);
147 }
Sam Clegge4afbc62018-11-14 18:36:24 +0000148 return 0;
149}
150
151int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnf208f632018-09-05 01:27:38 +0000152 WasmYAML::LinkingSection &Section) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000153 writeStringRef(Section.Name, OS);
Sam Clegg6bb5a412018-04-26 18:15:32 +0000154 encodeULEB128(Section.Version, OS);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000155
156 SubSectionWriter SubSection(OS);
157
Sam Clegg6c899ba2018-02-23 05:08:34 +0000158 // SYMBOL_TABLE subsection
159 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000160 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000161
Heejin Ahn18c56a02019-02-04 19:13:39 +0000162 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000163#ifndef NDEBUG
Sam Clegg6c899ba2018-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++);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000168 writeUint8(SubSection.getStream(), Info.Kind);
169 encodeULEB128(Info.Flags, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000170 switch (Info.Kind) {
171 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
172 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahnda419bd2018-11-14 02:46:21 +0000173 case wasm::WASM_SYMBOL_TYPE_EVENT:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000174 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Dan Gohman29874ce2019-02-07 22:03:32 +0000175 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
176 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Heejin Ahn18c56a02019-02-04 19:13:39 +0000177 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000178 break;
179 case wasm::WASM_SYMBOL_TYPE_DATA:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000180 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000181 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000182 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
183 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
184 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000185 }
186 break;
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000187 case wasm::WASM_SYMBOL_TYPE_SECTION:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000188 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000189 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
Heejin Ahn18c56a02019-02-04 19:13:39 +0000195 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);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000201 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
Sam Clegg63ebb812017-09-29 16:50:08 +0000202 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Heejin Ahn18c56a02019-02-04 19:13:39 +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 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000207 SubSection.done();
Sam Cleggd95ed952017-09-20 19:03:35 +0000208 }
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);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000213 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000214 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000215 encodeULEB128(Func.Priority, SubSection.getStream());
216 encodeULEB128(Func.Symbol, SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000217 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000218 SubSection.done();
Sam Clegg42739982017-12-14 21:10:03 +0000219 }
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);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000224 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000225 for (const auto &C : Section.Comdats) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000226 writeStringRef(C.Name, SubSection.getStream());
227 encodeULEB128(0, SubSection.getStream()); // flags for future use
228 encodeULEB128(C.Entries.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000229 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000230 writeUint8(SubSection.getStream(), Entry.Kind);
231 encodeULEB128(Entry.Index, SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000232 }
233 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000234 SubSection.done();
Sam Cleggea7cace2018-01-09 23:43:14 +0000235 }
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
Heejin Ahn18c56a02019-02-04 19:13:39 +0000248 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000249 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000250 encodeULEB128(NameEntry.Index, SubSection.getStream());
251 writeStringRef(NameEntry.Name, SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000252 }
253
Heejin Ahn18c56a02019-02-04 19:13:39 +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) {
Thomas Lively2e150402019-02-19 22:56:19 +0000490 encodeULEB128(Segment.InitFlags, OS);
491 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
492 encodeULEB128(Segment.MemoryIndex, OS);
493 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
494 writeInitExpr(Segment.Offset, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000495 encodeULEB128(Segment.Content.binary_size(), OS);
496 Segment.Content.writeAsBinary(OS);
497 }
498 return 0;
499}
500
Sam Clegg6f08c842018-04-24 18:11:36 +0000501int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
502 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000503 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000504 case wasm::WASM_SEC_CODE:
505 writeStringRef("reloc.CODE", OS);
506 break;
507 case wasm::WASM_SEC_DATA:
508 writeStringRef("reloc.DATA", OS);
509 break;
510 case wasm::WASM_SEC_CUSTOM: {
511 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
512 if (!CustomSection->Name.startswith(".debug_")) {
513 llvm_unreachable("not yet implemented (only for debug sections)");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000514 return 1;
Heejin Ahnf208f632018-09-05 01:27:38 +0000515 }
516
517 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
518 break;
519 }
520 default:
521 llvm_unreachable("not yet implemented");
522 return 1;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000523 }
524
Sam Clegg6f08c842018-04-24 18:11:36 +0000525 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000526 encodeULEB128(Sec.Relocations.size(), OS);
527
Heejin Ahnf208f632018-09-05 01:27:38 +0000528 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000529 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000530 encodeULEB128(Reloc.Offset, OS);
531 encodeULEB128(Reloc.Index, OS);
532 switch (Reloc.Type) {
Sam Cleggd1152a22019-02-04 17:28:46 +0000533 case wasm::R_WASM_MEMORY_ADDR_LEB:
534 case wasm::R_WASM_MEMORY_ADDR_SLEB:
535 case wasm::R_WASM_MEMORY_ADDR_I32:
536 case wasm::R_WASM_FUNCTION_OFFSET_I32:
537 case wasm::R_WASM_SECTION_OFFSET_I32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000538 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000539 }
540 }
541 return 0;
542}
543
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000544int WasmWriter::writeWasm(raw_ostream &OS) {
545 // Write headers
546 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
547 writeUint32(OS, Obj.Header.Version);
548
549 // Write each section
Heejin Ahnfeef7202018-12-15 00:58:12 +0000550 llvm::object::WasmSectionOrderChecker Checker;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000551 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Heejin Ahnfeef7202018-12-15 00:58:12 +0000552 StringRef SecName = "";
553 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
554 SecName = S->Name;
555 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
556 errs() << "Out of order section type: " << Sec->Type << "\n";
557 return 1;
558 }
Sam Clegge53af7f2018-01-09 21:38:53 +0000559 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000560 std::string OutString;
561 raw_string_ostream StringStream(OutString);
562 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
563 if (auto Err = writeSectionContent(StringStream, *S))
564 return Err;
565 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
566 if (auto Err = writeSectionContent(StringStream, *S))
567 return Err;
568 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
569 if (auto Err = writeSectionContent(StringStream, *S))
570 return Err;
571 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
572 if (auto Err = writeSectionContent(StringStream, *S))
573 return Err;
574 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
575 if (auto Err = writeSectionContent(StringStream, *S))
576 return Err;
577 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
578 if (auto Err = writeSectionContent(StringStream, *S))
579 return Err;
580 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
581 if (auto Err = writeSectionContent(StringStream, *S))
582 return Err;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000583 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
584 if (auto Err = writeSectionContent(StringStream, *S))
585 return Err;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000586 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
587 if (auto Err = writeSectionContent(StringStream, *S))
588 return Err;
589 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
590 if (auto Err = writeSectionContent(StringStream, *S))
591 return Err;
592 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
593 if (auto Err = writeSectionContent(StringStream, *S))
594 return Err;
595 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
596 if (auto Err = writeSectionContent(StringStream, *S))
597 return Err;
598 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
599 if (auto Err = writeSectionContent(StringStream, *S))
600 return Err;
601 } else {
602 errs() << "Unknown section type: " << Sec->Type << "\n";
603 return 1;
604 }
605 StringStream.flush();
606
607 // Write the section size followed by the content
608 encodeULEB128(OutString.size(), OS);
609 OS << OutString;
610 }
611
612 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000613 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000614 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000615 if (Sec->Relocations.empty()) {
616 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000617 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000618 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000619
Sam Clegg03e101f2018-03-01 18:06:21 +0000620 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000621 std::string OutString;
622 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000623 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000624 StringStream.flush();
625
626 encodeULEB128(OutString.size(), OS);
627 OS << OutString;
628 }
629
630 return 0;
631}
632
633int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
634 WasmWriter Writer(Doc);
635
636 return Writer.writeWasm(Out);
637}