blob: cd07a30b74873692c80cf6d4217770bafc9cd6db [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);
Thomas Livelyfef8de62019-04-12 22:27:48 +000046 int writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000047
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);
Thomas Livelyf6f4f842019-03-20 20:26:45 +000053 int writeSectionContent(raw_ostream &OS,
54 WasmYAML::TargetFeaturesSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000055 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000056 uint32_t NumImportedFunctions = 0;
57 uint32_t NumImportedGlobals = 0;
Heejin Ahnda419bd2018-11-14 02:46:21 +000058 uint32_t NumImportedEvents = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +000059};
60
61static int writeUint64(raw_ostream &OS, uint64_t Value) {
62 char Data[sizeof(Value)];
63 support::endian::write64le(Data, Value);
64 OS.write(Data, sizeof(Data));
65 return 0;
66}
67
68static int writeUint32(raw_ostream &OS, uint32_t Value) {
69 char Data[sizeof(Value)];
70 support::endian::write32le(Data, Value);
71 OS.write(Data, sizeof(Data));
72 return 0;
73}
74
75static int writeUint8(raw_ostream &OS, uint8_t Value) {
76 char Data[sizeof(Value)];
77 memcpy(Data, &Value, sizeof(Data));
78 OS.write(Data, sizeof(Data));
79 return 0;
80}
81
Sam Clegg03cdd122017-05-05 18:12:34 +000082static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000083 encodeULEB128(Str.size(), OS);
84 OS << Str;
85 return 0;
86}
87
Sam Clegg03cdd122017-05-05 18:12:34 +000088static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +000089 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000090 encodeULEB128(Lim.Initial, OS);
91 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
92 encodeULEB128(Lim.Maximum, OS);
93 return 0;
94}
95
Sam Clegg03cdd122017-05-05 18:12:34 +000096static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000097 writeUint8(OS, InitExpr.Opcode);
98 switch (InitExpr.Opcode) {
99 case wasm::WASM_OPCODE_I32_CONST:
100 encodeSLEB128(InitExpr.Value.Int32, OS);
101 break;
102 case wasm::WASM_OPCODE_I64_CONST:
103 encodeSLEB128(InitExpr.Value.Int64, OS);
104 break;
105 case wasm::WASM_OPCODE_F32_CONST:
106 writeUint32(OS, InitExpr.Value.Float32);
107 break;
108 case wasm::WASM_OPCODE_F64_CONST:
109 writeUint64(OS, InitExpr.Value.Float64);
110 break;
Thomas Lively6a87dda2019-01-08 06:25:55 +0000111 case wasm::WASM_OPCODE_GLOBAL_GET:
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000112 encodeULEB128(InitExpr.Value.Global, OS);
113 break;
114 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000115 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000116 return 1;
117 }
118 writeUint8(OS, wasm::WASM_OPCODE_END);
119 return 0;
120}
121
Sam Clegg9e1ade92017-06-27 20:27:59 +0000122class SubSectionWriter {
123 raw_ostream &OS;
124 std::string OutString;
125 raw_string_ostream StringStream;
Sam Cleggb7787fd2017-06-20 04:04:59 +0000126
Sam Clegg9e1ade92017-06-27 20:27:59 +0000127public:
128 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Cleggb7787fd2017-06-20 04:04:59 +0000129
Heejin Ahn18c56a02019-02-04 19:13:39 +0000130 void done() {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000131 StringStream.flush();
132 encodeULEB128(OutString.size(), OS);
133 OS << OutString;
Sam Clegg9e1ade92017-06-27 20:27:59 +0000134 OutString.clear();
135 }
136
Heejin Ahn18c56a02019-02-04 19:13:39 +0000137 raw_ostream &getStream() { return StringStream; }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000138};
139
Heejin Ahnf208f632018-09-05 01:27:38 +0000140int WasmWriter::writeSectionContent(raw_ostream &OS,
Sam Clegge4afbc62018-11-14 18:36:24 +0000141 WasmYAML::DylinkSection &Section) {
142 writeStringRef(Section.Name, OS);
143 encodeULEB128(Section.MemorySize, OS);
144 encodeULEB128(Section.MemoryAlignment, OS);
145 encodeULEB128(Section.TableSize, OS);
146 encodeULEB128(Section.TableAlignment, OS);
Sam Clegg03801252018-12-12 23:40:58 +0000147 encodeULEB128(Section.Needed.size(), OS);
148 for (StringRef Needed : Section.Needed) {
149 writeStringRef(Needed, OS);
150 }
Sam Clegge4afbc62018-11-14 18:36:24 +0000151 return 0;
152}
153
154int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnf208f632018-09-05 01:27:38 +0000155 WasmYAML::LinkingSection &Section) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000156 writeStringRef(Section.Name, OS);
Sam Clegg6bb5a412018-04-26 18:15:32 +0000157 encodeULEB128(Section.Version, OS);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000158
159 SubSectionWriter SubSection(OS);
160
Sam Clegg6c899ba2018-02-23 05:08:34 +0000161 // SYMBOL_TABLE subsection
162 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000163 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000164
Heejin Ahn18c56a02019-02-04 19:13:39 +0000165 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000166#ifndef NDEBUG
Sam Clegg6c899ba2018-02-23 05:08:34 +0000167 uint32_t SymbolIndex = 0;
168#endif
169 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
170 assert(Info.Index == SymbolIndex++);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000171 writeUint8(SubSection.getStream(), Info.Kind);
172 encodeULEB128(Info.Flags, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000173 switch (Info.Kind) {
174 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
175 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahnda419bd2018-11-14 02:46:21 +0000176 case wasm::WASM_SYMBOL_TYPE_EVENT:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000177 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Dan Gohman29874ce2019-02-07 22:03:32 +0000178 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
179 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Heejin Ahn18c56a02019-02-04 19:13:39 +0000180 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000181 break;
182 case wasm::WASM_SYMBOL_TYPE_DATA:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000183 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000184 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000185 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
186 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
187 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000188 }
189 break;
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000190 case wasm::WASM_SYMBOL_TYPE_SECTION:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000191 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000192 break;
Sam Clegg6c899ba2018-02-23 05:08:34 +0000193 default:
194 llvm_unreachable("unexpected kind");
195 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000196 }
197
Heejin Ahn18c56a02019-02-04 19:13:39 +0000198 SubSection.done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000199 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000200
201 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000202 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000203 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000204 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
Sam Clegg63ebb812017-09-29 16:50:08 +0000205 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000206 writeStringRef(SegmentInfo.Name, SubSection.getStream());
207 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
208 encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000209 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000210 SubSection.done();
Sam Cleggd95ed952017-09-20 19:03:35 +0000211 }
Sam Clegg42739982017-12-14 21:10:03 +0000212
213 // INIT_FUNCS subsection
214 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000215 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000216 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000217 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000218 encodeULEB128(Func.Priority, SubSection.getStream());
219 encodeULEB128(Func.Symbol, SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000220 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000221 SubSection.done();
Sam Clegg42739982017-12-14 21:10:03 +0000222 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000223
224 // COMDAT_INFO subsection
225 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000226 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000227 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000228 for (const auto &C : Section.Comdats) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000229 writeStringRef(C.Name, SubSection.getStream());
230 encodeULEB128(0, SubSection.getStream()); // flags for future use
231 encodeULEB128(C.Entries.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000232 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000233 writeUint8(SubSection.getStream(), Entry.Kind);
234 encodeULEB128(Entry.Index, SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000235 }
236 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000237 SubSection.done();
Sam Cleggea7cace2018-01-09 23:43:14 +0000238 }
239
Sam Cleggb7787fd2017-06-20 04:04:59 +0000240 return 0;
241}
242
Heejin Ahnf208f632018-09-05 01:27:38 +0000243int WasmWriter::writeSectionContent(raw_ostream &OS,
244 WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000245 writeStringRef(Section.Name, OS);
246 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000247 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000248
Sam Clegg9e1ade92017-06-27 20:27:59 +0000249 SubSectionWriter SubSection(OS);
250
Heejin Ahn18c56a02019-02-04 19:13:39 +0000251 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000252 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000253 encodeULEB128(NameEntry.Index, SubSection.getStream());
254 writeStringRef(NameEntry.Name, SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000255 }
256
Heejin Ahn18c56a02019-02-04 19:13:39 +0000257 SubSection.done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000258 }
259 return 0;
260}
261
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000262int WasmWriter::writeSectionContent(raw_ostream &OS,
Thomas Livelycbda16e2019-01-17 02:29:55 +0000263 WasmYAML::ProducersSection &Section) {
264 writeStringRef(Section.Name, OS);
265 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
266 int(!Section.SDKs.empty());
267 if (Fields == 0)
268 return 0;
269 encodeULEB128(Fields, OS);
270 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
271 std::make_pair(StringRef("processed-by"), &Section.Tools),
272 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
273 if (Field.second->empty())
274 continue;
275 writeStringRef(Field.first, OS);
276 encodeULEB128(Field.second->size(), OS);
277 for (auto &Entry : *Field.second) {
278 writeStringRef(Entry.Name, OS);
279 writeStringRef(Entry.Version, OS);
280 }
281 }
282 return 0;
283}
284
285int WasmWriter::writeSectionContent(raw_ostream &OS,
Thomas Livelyf6f4f842019-03-20 20:26:45 +0000286 WasmYAML::TargetFeaturesSection &Section) {
287 writeStringRef(Section.Name, OS);
288 encodeULEB128(Section.Features.size(), OS);
289 for (auto &E : Section.Features) {
290 writeUint8(OS, E.Prefix);
291 writeStringRef(E.Name, OS);
292 }
293 return 0;
294}
295
296int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000297 WasmYAML::CustomSection &Section) {
Sam Clegge4afbc62018-11-14 18:36:24 +0000298 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
299 if (auto Err = writeSectionContent(OS, *S))
300 return Err;
301 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000302 if (auto Err = writeSectionContent(OS, *S))
303 return Err;
304 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
305 if (auto Err = writeSectionContent(OS, *S))
306 return Err;
Thomas Livelycbda16e2019-01-17 02:29:55 +0000307 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
308 if (auto Err = writeSectionContent(OS, *S))
309 return Err;
Thomas Livelyf6f4f842019-03-20 20:26:45 +0000310 } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
311 if (auto Err = writeSectionContent(OS, *S))
312 return Err;
Sam Clegg03cdd122017-05-05 18:12:34 +0000313 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000314 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000315 Section.Payload.writeAsBinary(OS);
316 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000317 return 0;
318}
319
320int WasmWriter::writeSectionContent(raw_ostream &OS,
321 WasmYAML::TypeSection &Section) {
322 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000323 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000324 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000325 if (Sig.Index != ExpectedIndex) {
326 errs() << "Unexpected type index: " << Sig.Index << "\n";
327 return 1;
328 }
329 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000330 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000331 encodeULEB128(Sig.ParamTypes.size(), OS);
332 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000333 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000334 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000335 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000336 } else {
337 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000338 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000339 }
340 }
341 return 0;
342}
343
344int WasmWriter::writeSectionContent(raw_ostream &OS,
345 WasmYAML::ImportSection &Section) {
346 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000347 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000348 writeStringRef(Import.Module, OS);
349 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000350 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000351 switch (Import.Kind) {
352 case wasm::WASM_EXTERNAL_FUNCTION:
353 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000354 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000355 break;
356 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000357 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000358 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000359 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000360 break;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000361 case wasm::WASM_EXTERNAL_EVENT:
362 writeUint32(OS, Import.EventImport.Attribute);
363 writeUint32(OS, Import.EventImport.SigIndex);
364 NumImportedGlobals++;
365 break;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000366 case wasm::WASM_EXTERNAL_MEMORY:
367 writeLimits(Import.Memory, OS);
368 break;
369 case wasm::WASM_EXTERNAL_TABLE:
Heejin Ahnf208f632018-09-05 01:27:38 +0000370 writeUint8(OS, Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000371 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000372 break;
373 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000374 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000375 return 1;
376 }
377 }
378 return 0;
379}
380
381int WasmWriter::writeSectionContent(raw_ostream &OS,
382 WasmYAML::FunctionSection &Section) {
383 encodeULEB128(Section.FunctionTypes.size(), OS);
384 for (uint32_t FuncType : Section.FunctionTypes) {
385 encodeULEB128(FuncType, OS);
386 }
387 return 0;
388}
389
390int WasmWriter::writeSectionContent(raw_ostream &OS,
391 WasmYAML::ExportSection &Section) {
392 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000393 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000394 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000395 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000396 encodeULEB128(Export.Index, OS);
397 }
398 return 0;
399}
400
401int WasmWriter::writeSectionContent(raw_ostream &OS,
402 WasmYAML::StartSection &Section) {
403 encodeULEB128(Section.StartFunction, OS);
404 return 0;
405}
406
407int WasmWriter::writeSectionContent(raw_ostream &OS,
408 WasmYAML::TableSection &Section) {
409 encodeULEB128(Section.Tables.size(), OS);
410 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000411 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000412 writeLimits(Table.TableLimits, OS);
413 }
414 return 0;
415}
416
417int WasmWriter::writeSectionContent(raw_ostream &OS,
418 WasmYAML::MemorySection &Section) {
419 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000420 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000421 writeLimits(Mem, OS);
422 }
423 return 0;
424}
425
426int WasmWriter::writeSectionContent(raw_ostream &OS,
427 WasmYAML::GlobalSection &Section) {
428 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000429 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000430 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000431 if (Global.Index != ExpectedIndex) {
432 errs() << "Unexpected global index: " << Global.Index << "\n";
433 return 1;
434 }
435 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000436 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000437 writeUint8(OS, Global.Mutable);
438 writeInitExpr(Global.InitExpr, OS);
439 }
440 return 0;
441}
442
443int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnda419bd2018-11-14 02:46:21 +0000444 WasmYAML::EventSection &Section) {
445 encodeULEB128(Section.Events.size(), OS);
446 uint32_t ExpectedIndex = NumImportedEvents;
447 for (auto &Event : Section.Events) {
448 if (Event.Index != ExpectedIndex) {
449 errs() << "Unexpected event index: " << Event.Index << "\n";
450 return 1;
451 }
452 ++ExpectedIndex;
453 encodeULEB128(Event.Attribute, OS);
454 encodeULEB128(Event.SigIndex, OS);
455 }
456 return 0;
457}
458
459int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000460 WasmYAML::ElemSection &Section) {
461 encodeULEB128(Section.Segments.size(), OS);
462 for (auto &Segment : Section.Segments) {
463 encodeULEB128(Segment.TableIndex, OS);
464 writeInitExpr(Segment.Offset, OS);
465
466 encodeULEB128(Segment.Functions.size(), OS);
467 for (auto &Function : Segment.Functions) {
468 encodeULEB128(Function, OS);
469 }
470 }
471 return 0;
472}
473
474int WasmWriter::writeSectionContent(raw_ostream &OS,
475 WasmYAML::CodeSection &Section) {
476 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000477 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000478 for (auto &Func : Section.Functions) {
479 std::string OutString;
480 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000481 if (Func.Index != ExpectedIndex) {
482 errs() << "Unexpected function index: " << Func.Index << "\n";
483 return 1;
484 }
485 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000486
487 encodeULEB128(Func.Locals.size(), StringStream);
488 for (auto &LocalDecl : Func.Locals) {
489 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000490 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000491 }
492
493 Func.Body.writeAsBinary(StringStream);
494
495 // Write the section size followed by the content
496 StringStream.flush();
497 encodeULEB128(OutString.size(), OS);
498 OS << OutString;
499 }
500 return 0;
501}
502
503int WasmWriter::writeSectionContent(raw_ostream &OS,
504 WasmYAML::DataSection &Section) {
505 encodeULEB128(Section.Segments.size(), OS);
506 for (auto &Segment : Section.Segments) {
Thomas Lively2e150402019-02-19 22:56:19 +0000507 encodeULEB128(Segment.InitFlags, OS);
508 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
509 encodeULEB128(Segment.MemoryIndex, OS);
510 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
511 writeInitExpr(Segment.Offset, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000512 encodeULEB128(Segment.Content.binary_size(), OS);
513 Segment.Content.writeAsBinary(OS);
514 }
515 return 0;
516}
517
Thomas Livelyfef8de62019-04-12 22:27:48 +0000518int WasmWriter::writeSectionContent(raw_ostream &OS,
519 WasmYAML::DataCountSection &Section) {
520 encodeULEB128(Section.Count, OS);
521 return 0;
522}
523
Sam Clegg6f08c842018-04-24 18:11:36 +0000524int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
525 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000526 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000527 case wasm::WASM_SEC_CODE:
528 writeStringRef("reloc.CODE", OS);
529 break;
530 case wasm::WASM_SEC_DATA:
531 writeStringRef("reloc.DATA", OS);
532 break;
533 case wasm::WASM_SEC_CUSTOM: {
534 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
535 if (!CustomSection->Name.startswith(".debug_")) {
536 llvm_unreachable("not yet implemented (only for debug sections)");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000537 return 1;
Heejin Ahnf208f632018-09-05 01:27:38 +0000538 }
539
540 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
541 break;
542 }
543 default:
544 llvm_unreachable("not yet implemented");
545 return 1;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000546 }
547
Sam Clegg6f08c842018-04-24 18:11:36 +0000548 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000549 encodeULEB128(Sec.Relocations.size(), OS);
550
Heejin Ahnf208f632018-09-05 01:27:38 +0000551 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000552 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000553 encodeULEB128(Reloc.Offset, OS);
554 encodeULEB128(Reloc.Index, OS);
555 switch (Reloc.Type) {
Sam Cleggd1152a22019-02-04 17:28:46 +0000556 case wasm::R_WASM_MEMORY_ADDR_LEB:
557 case wasm::R_WASM_MEMORY_ADDR_SLEB:
558 case wasm::R_WASM_MEMORY_ADDR_I32:
559 case wasm::R_WASM_FUNCTION_OFFSET_I32:
560 case wasm::R_WASM_SECTION_OFFSET_I32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000561 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000562 }
563 }
564 return 0;
565}
566
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000567int WasmWriter::writeWasm(raw_ostream &OS) {
568 // Write headers
569 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
570 writeUint32(OS, Obj.Header.Version);
571
572 // Write each section
Heejin Ahnfeef7202018-12-15 00:58:12 +0000573 llvm::object::WasmSectionOrderChecker Checker;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000574 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Heejin Ahnfeef7202018-12-15 00:58:12 +0000575 StringRef SecName = "";
576 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
577 SecName = S->Name;
578 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
579 errs() << "Out of order section type: " << Sec->Type << "\n";
580 return 1;
581 }
Sam Clegge53af7f2018-01-09 21:38:53 +0000582 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000583 std::string OutString;
584 raw_string_ostream StringStream(OutString);
585 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
586 if (auto Err = writeSectionContent(StringStream, *S))
587 return Err;
588 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
589 if (auto Err = writeSectionContent(StringStream, *S))
590 return Err;
591 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
592 if (auto Err = writeSectionContent(StringStream, *S))
593 return Err;
594 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
595 if (auto Err = writeSectionContent(StringStream, *S))
596 return Err;
597 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
598 if (auto Err = writeSectionContent(StringStream, *S))
599 return Err;
600 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
601 if (auto Err = writeSectionContent(StringStream, *S))
602 return Err;
603 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
604 if (auto Err = writeSectionContent(StringStream, *S))
605 return Err;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000606 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
607 if (auto Err = writeSectionContent(StringStream, *S))
608 return Err;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000609 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
610 if (auto Err = writeSectionContent(StringStream, *S))
611 return Err;
612 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
613 if (auto Err = writeSectionContent(StringStream, *S))
614 return Err;
615 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
616 if (auto Err = writeSectionContent(StringStream, *S))
617 return Err;
618 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
619 if (auto Err = writeSectionContent(StringStream, *S))
620 return Err;
621 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
622 if (auto Err = writeSectionContent(StringStream, *S))
623 return Err;
Thomas Livelyfef8de62019-04-12 22:27:48 +0000624 } else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get())) {
625 if (auto Err = writeSectionContent(StringStream, *S))
626 return Err;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000627 } else {
628 errs() << "Unknown section type: " << Sec->Type << "\n";
629 return 1;
630 }
631 StringStream.flush();
632
633 // Write the section size followed by the content
634 encodeULEB128(OutString.size(), OS);
635 OS << OutString;
636 }
637
638 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000639 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000640 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000641 if (Sec->Relocations.empty()) {
642 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000643 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000644 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000645
Sam Clegg03e101f2018-03-01 18:06:21 +0000646 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000647 std::string OutString;
648 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000649 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000650 StringStream.flush();
651
652 encodeULEB128(OutString.size(), OS);
653 OS << OutString;
654 }
655
656 return 0;
657}
658
659int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
660 WasmWriter Writer(Doc);
661
662 return Writer.writeWasm(Out);
663}