blob: a0600c68d910c3909095bcc2ec9c8aacbeae57df [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());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000175 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0)
Heejin Ahn18c56a02019-02-04 19:13:39 +0000176 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000177 break;
178 case wasm::WASM_SYMBOL_TYPE_DATA:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000179 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000180 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000181 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
182 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
183 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000184 }
185 break;
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000186 case wasm::WASM_SYMBOL_TYPE_SECTION:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000187 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000188 break;
Sam Clegg6c899ba2018-02-23 05:08:34 +0000189 default:
190 llvm_unreachable("unexpected kind");
191 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000192 }
193
Heejin Ahn18c56a02019-02-04 19:13:39 +0000194 SubSection.done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000195 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000196
197 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000198 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000199 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000200 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
Sam Clegg63ebb812017-09-29 16:50:08 +0000201 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000202 writeStringRef(SegmentInfo.Name, SubSection.getStream());
203 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
204 encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000205 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000206 SubSection.done();
Sam Cleggd95ed952017-09-20 19:03:35 +0000207 }
Sam Clegg42739982017-12-14 21:10:03 +0000208
209 // INIT_FUNCS subsection
210 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000211 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000212 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000213 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000214 encodeULEB128(Func.Priority, SubSection.getStream());
215 encodeULEB128(Func.Symbol, SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000216 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000217 SubSection.done();
Sam Clegg42739982017-12-14 21:10:03 +0000218 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000219
220 // COMDAT_INFO subsection
221 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000222 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000223 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000224 for (const auto &C : Section.Comdats) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000225 writeStringRef(C.Name, SubSection.getStream());
226 encodeULEB128(0, SubSection.getStream()); // flags for future use
227 encodeULEB128(C.Entries.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000228 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000229 writeUint8(SubSection.getStream(), Entry.Kind);
230 encodeULEB128(Entry.Index, SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000231 }
232 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000233 SubSection.done();
Sam Cleggea7cace2018-01-09 23:43:14 +0000234 }
235
Sam Cleggb7787fd2017-06-20 04:04:59 +0000236 return 0;
237}
238
Heejin Ahnf208f632018-09-05 01:27:38 +0000239int WasmWriter::writeSectionContent(raw_ostream &OS,
240 WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000241 writeStringRef(Section.Name, OS);
242 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000243 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000244
Sam Clegg9e1ade92017-06-27 20:27:59 +0000245 SubSectionWriter SubSection(OS);
246
Heejin Ahn18c56a02019-02-04 19:13:39 +0000247 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000248 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000249 encodeULEB128(NameEntry.Index, SubSection.getStream());
250 writeStringRef(NameEntry.Name, SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000251 }
252
Heejin Ahn18c56a02019-02-04 19:13:39 +0000253 SubSection.done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000254 }
255 return 0;
256}
257
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000258int WasmWriter::writeSectionContent(raw_ostream &OS,
Thomas Livelycbda16e2019-01-17 02:29:55 +0000259 WasmYAML::ProducersSection &Section) {
260 writeStringRef(Section.Name, OS);
261 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
262 int(!Section.SDKs.empty());
263 if (Fields == 0)
264 return 0;
265 encodeULEB128(Fields, OS);
266 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
267 std::make_pair(StringRef("processed-by"), &Section.Tools),
268 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
269 if (Field.second->empty())
270 continue;
271 writeStringRef(Field.first, OS);
272 encodeULEB128(Field.second->size(), OS);
273 for (auto &Entry : *Field.second) {
274 writeStringRef(Entry.Name, OS);
275 writeStringRef(Entry.Version, OS);
276 }
277 }
278 return 0;
279}
280
281int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000282 WasmYAML::CustomSection &Section) {
Sam Clegge4afbc62018-11-14 18:36:24 +0000283 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
284 if (auto Err = writeSectionContent(OS, *S))
285 return Err;
286 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000287 if (auto Err = writeSectionContent(OS, *S))
288 return Err;
289 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
290 if (auto Err = writeSectionContent(OS, *S))
291 return Err;
Thomas Livelycbda16e2019-01-17 02:29:55 +0000292 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
293 if (auto Err = writeSectionContent(OS, *S))
294 return Err;
Sam Clegg03cdd122017-05-05 18:12:34 +0000295 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000296 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000297 Section.Payload.writeAsBinary(OS);
298 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000299 return 0;
300}
301
302int WasmWriter::writeSectionContent(raw_ostream &OS,
303 WasmYAML::TypeSection &Section) {
304 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000305 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000306 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000307 if (Sig.Index != ExpectedIndex) {
308 errs() << "Unexpected type index: " << Sig.Index << "\n";
309 return 1;
310 }
311 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000312 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000313 encodeULEB128(Sig.ParamTypes.size(), OS);
314 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000315 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000316 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000317 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000318 } else {
319 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000320 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000321 }
322 }
323 return 0;
324}
325
326int WasmWriter::writeSectionContent(raw_ostream &OS,
327 WasmYAML::ImportSection &Section) {
328 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000329 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000330 writeStringRef(Import.Module, OS);
331 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000332 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000333 switch (Import.Kind) {
334 case wasm::WASM_EXTERNAL_FUNCTION:
335 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000336 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000337 break;
338 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000339 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000340 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000341 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000342 break;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000343 case wasm::WASM_EXTERNAL_EVENT:
344 writeUint32(OS, Import.EventImport.Attribute);
345 writeUint32(OS, Import.EventImport.SigIndex);
346 NumImportedGlobals++;
347 break;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000348 case wasm::WASM_EXTERNAL_MEMORY:
349 writeLimits(Import.Memory, OS);
350 break;
351 case wasm::WASM_EXTERNAL_TABLE:
Heejin Ahnf208f632018-09-05 01:27:38 +0000352 writeUint8(OS, Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000353 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000354 break;
355 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000356 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000357 return 1;
358 }
359 }
360 return 0;
361}
362
363int WasmWriter::writeSectionContent(raw_ostream &OS,
364 WasmYAML::FunctionSection &Section) {
365 encodeULEB128(Section.FunctionTypes.size(), OS);
366 for (uint32_t FuncType : Section.FunctionTypes) {
367 encodeULEB128(FuncType, OS);
368 }
369 return 0;
370}
371
372int WasmWriter::writeSectionContent(raw_ostream &OS,
373 WasmYAML::ExportSection &Section) {
374 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000375 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000376 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000377 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000378 encodeULEB128(Export.Index, OS);
379 }
380 return 0;
381}
382
383int WasmWriter::writeSectionContent(raw_ostream &OS,
384 WasmYAML::StartSection &Section) {
385 encodeULEB128(Section.StartFunction, OS);
386 return 0;
387}
388
389int WasmWriter::writeSectionContent(raw_ostream &OS,
390 WasmYAML::TableSection &Section) {
391 encodeULEB128(Section.Tables.size(), OS);
392 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000393 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000394 writeLimits(Table.TableLimits, OS);
395 }
396 return 0;
397}
398
399int WasmWriter::writeSectionContent(raw_ostream &OS,
400 WasmYAML::MemorySection &Section) {
401 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000402 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000403 writeLimits(Mem, OS);
404 }
405 return 0;
406}
407
408int WasmWriter::writeSectionContent(raw_ostream &OS,
409 WasmYAML::GlobalSection &Section) {
410 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000411 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000412 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000413 if (Global.Index != ExpectedIndex) {
414 errs() << "Unexpected global index: " << Global.Index << "\n";
415 return 1;
416 }
417 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000418 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000419 writeUint8(OS, Global.Mutable);
420 writeInitExpr(Global.InitExpr, OS);
421 }
422 return 0;
423}
424
425int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnda419bd2018-11-14 02:46:21 +0000426 WasmYAML::EventSection &Section) {
427 encodeULEB128(Section.Events.size(), OS);
428 uint32_t ExpectedIndex = NumImportedEvents;
429 for (auto &Event : Section.Events) {
430 if (Event.Index != ExpectedIndex) {
431 errs() << "Unexpected event index: " << Event.Index << "\n";
432 return 1;
433 }
434 ++ExpectedIndex;
435 encodeULEB128(Event.Attribute, OS);
436 encodeULEB128(Event.SigIndex, OS);
437 }
438 return 0;
439}
440
441int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000442 WasmYAML::ElemSection &Section) {
443 encodeULEB128(Section.Segments.size(), OS);
444 for (auto &Segment : Section.Segments) {
445 encodeULEB128(Segment.TableIndex, OS);
446 writeInitExpr(Segment.Offset, OS);
447
448 encodeULEB128(Segment.Functions.size(), OS);
449 for (auto &Function : Segment.Functions) {
450 encodeULEB128(Function, OS);
451 }
452 }
453 return 0;
454}
455
456int WasmWriter::writeSectionContent(raw_ostream &OS,
457 WasmYAML::CodeSection &Section) {
458 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000459 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000460 for (auto &Func : Section.Functions) {
461 std::string OutString;
462 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000463 if (Func.Index != ExpectedIndex) {
464 errs() << "Unexpected function index: " << Func.Index << "\n";
465 return 1;
466 }
467 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000468
469 encodeULEB128(Func.Locals.size(), StringStream);
470 for (auto &LocalDecl : Func.Locals) {
471 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000472 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000473 }
474
475 Func.Body.writeAsBinary(StringStream);
476
477 // Write the section size followed by the content
478 StringStream.flush();
479 encodeULEB128(OutString.size(), OS);
480 OS << OutString;
481 }
482 return 0;
483}
484
485int WasmWriter::writeSectionContent(raw_ostream &OS,
486 WasmYAML::DataSection &Section) {
487 encodeULEB128(Section.Segments.size(), OS);
488 for (auto &Segment : Section.Segments) {
Sam Clegg9c07f942017-07-12 00:24:54 +0000489 encodeULEB128(Segment.MemoryIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000490 writeInitExpr(Segment.Offset, OS);
491 encodeULEB128(Segment.Content.binary_size(), OS);
492 Segment.Content.writeAsBinary(OS);
493 }
494 return 0;
495}
496
Sam Clegg6f08c842018-04-24 18:11:36 +0000497int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
498 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000499 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000500 case wasm::WASM_SEC_CODE:
501 writeStringRef("reloc.CODE", OS);
502 break;
503 case wasm::WASM_SEC_DATA:
504 writeStringRef("reloc.DATA", OS);
505 break;
506 case wasm::WASM_SEC_CUSTOM: {
507 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
508 if (!CustomSection->Name.startswith(".debug_")) {
509 llvm_unreachable("not yet implemented (only for debug sections)");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000510 return 1;
Heejin Ahnf208f632018-09-05 01:27:38 +0000511 }
512
513 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
514 break;
515 }
516 default:
517 llvm_unreachable("not yet implemented");
518 return 1;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000519 }
520
Sam Clegg6f08c842018-04-24 18:11:36 +0000521 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000522 encodeULEB128(Sec.Relocations.size(), OS);
523
Heejin Ahnf208f632018-09-05 01:27:38 +0000524 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000525 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000526 encodeULEB128(Reloc.Offset, OS);
527 encodeULEB128(Reloc.Index, OS);
528 switch (Reloc.Type) {
Sam Cleggd1152a22019-02-04 17:28:46 +0000529 case wasm::R_WASM_MEMORY_ADDR_LEB:
530 case wasm::R_WASM_MEMORY_ADDR_SLEB:
531 case wasm::R_WASM_MEMORY_ADDR_I32:
532 case wasm::R_WASM_FUNCTION_OFFSET_I32:
533 case wasm::R_WASM_SECTION_OFFSET_I32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000534 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000535 }
536 }
537 return 0;
538}
539
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000540int WasmWriter::writeWasm(raw_ostream &OS) {
541 // Write headers
542 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
543 writeUint32(OS, Obj.Header.Version);
544
545 // Write each section
Heejin Ahnfeef7202018-12-15 00:58:12 +0000546 llvm::object::WasmSectionOrderChecker Checker;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000547 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Heejin Ahnfeef7202018-12-15 00:58:12 +0000548 StringRef SecName = "";
549 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
550 SecName = S->Name;
551 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
552 errs() << "Out of order section type: " << Sec->Type << "\n";
553 return 1;
554 }
Sam Clegge53af7f2018-01-09 21:38:53 +0000555 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000556 std::string OutString;
557 raw_string_ostream StringStream(OutString);
558 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
559 if (auto Err = writeSectionContent(StringStream, *S))
560 return Err;
561 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
562 if (auto Err = writeSectionContent(StringStream, *S))
563 return Err;
564 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
565 if (auto Err = writeSectionContent(StringStream, *S))
566 return Err;
567 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
568 if (auto Err = writeSectionContent(StringStream, *S))
569 return Err;
570 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
571 if (auto Err = writeSectionContent(StringStream, *S))
572 return Err;
573 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
574 if (auto Err = writeSectionContent(StringStream, *S))
575 return Err;
576 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
577 if (auto Err = writeSectionContent(StringStream, *S))
578 return Err;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000579 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
580 if (auto Err = writeSectionContent(StringStream, *S))
581 return Err;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000582 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
583 if (auto Err = writeSectionContent(StringStream, *S))
584 return Err;
585 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
586 if (auto Err = writeSectionContent(StringStream, *S))
587 return Err;
588 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
589 if (auto Err = writeSectionContent(StringStream, *S))
590 return Err;
591 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
592 if (auto Err = writeSectionContent(StringStream, *S))
593 return Err;
594 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
595 if (auto Err = writeSectionContent(StringStream, *S))
596 return Err;
597 } else {
598 errs() << "Unknown section type: " << Sec->Type << "\n";
599 return 1;
600 }
601 StringStream.flush();
602
603 // Write the section size followed by the content
604 encodeULEB128(OutString.size(), OS);
605 OS << OutString;
606 }
607
608 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000609 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000610 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000611 if (Sec->Relocations.empty()) {
612 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000613 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000614 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000615
Sam Clegg03e101f2018-03-01 18:06:21 +0000616 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000617 std::string OutString;
618 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000619 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000620 StringStream.flush();
621
622 encodeULEB128(OutString.size(), OS);
623 OS << OutString;
624 }
625
626 return 0;
627}
628
629int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
630 WasmWriter Writer(Doc);
631
632 return Writer.writeWasm(Out);
633}