blob: 322ac0117badd6fad04026368a3f021b773add66 [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);
Thomas Livelyf6f4f842019-03-20 20:26:45 +000052 int writeSectionContent(raw_ostream &OS,
53 WasmYAML::TargetFeaturesSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000054 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000055 uint32_t NumImportedFunctions = 0;
56 uint32_t NumImportedGlobals = 0;
Heejin Ahnda419bd2018-11-14 02:46:21 +000057 uint32_t NumImportedEvents = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +000058};
59
60static int writeUint64(raw_ostream &OS, uint64_t Value) {
61 char Data[sizeof(Value)];
62 support::endian::write64le(Data, Value);
63 OS.write(Data, sizeof(Data));
64 return 0;
65}
66
67static int writeUint32(raw_ostream &OS, uint32_t Value) {
68 char Data[sizeof(Value)];
69 support::endian::write32le(Data, Value);
70 OS.write(Data, sizeof(Data));
71 return 0;
72}
73
74static int writeUint8(raw_ostream &OS, uint8_t Value) {
75 char Data[sizeof(Value)];
76 memcpy(Data, &Value, sizeof(Data));
77 OS.write(Data, sizeof(Data));
78 return 0;
79}
80
Sam Clegg03cdd122017-05-05 18:12:34 +000081static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000082 encodeULEB128(Str.size(), OS);
83 OS << Str;
84 return 0;
85}
86
Sam Clegg03cdd122017-05-05 18:12:34 +000087static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +000088 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000089 encodeULEB128(Lim.Initial, OS);
90 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
91 encodeULEB128(Lim.Maximum, OS);
92 return 0;
93}
94
Sam Clegg03cdd122017-05-05 18:12:34 +000095static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000096 writeUint8(OS, InitExpr.Opcode);
97 switch (InitExpr.Opcode) {
98 case wasm::WASM_OPCODE_I32_CONST:
99 encodeSLEB128(InitExpr.Value.Int32, OS);
100 break;
101 case wasm::WASM_OPCODE_I64_CONST:
102 encodeSLEB128(InitExpr.Value.Int64, OS);
103 break;
104 case wasm::WASM_OPCODE_F32_CONST:
105 writeUint32(OS, InitExpr.Value.Float32);
106 break;
107 case wasm::WASM_OPCODE_F64_CONST:
108 writeUint64(OS, InitExpr.Value.Float64);
109 break;
Thomas Lively6a87dda2019-01-08 06:25:55 +0000110 case wasm::WASM_OPCODE_GLOBAL_GET:
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000111 encodeULEB128(InitExpr.Value.Global, OS);
112 break;
113 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000114 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000115 return 1;
116 }
117 writeUint8(OS, wasm::WASM_OPCODE_END);
118 return 0;
119}
120
Sam Clegg9e1ade92017-06-27 20:27:59 +0000121class SubSectionWriter {
122 raw_ostream &OS;
123 std::string OutString;
124 raw_string_ostream StringStream;
Sam Cleggb7787fd2017-06-20 04:04:59 +0000125
Sam Clegg9e1ade92017-06-27 20:27:59 +0000126public:
127 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
Sam Cleggb7787fd2017-06-20 04:04:59 +0000128
Heejin Ahn18c56a02019-02-04 19:13:39 +0000129 void done() {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000130 StringStream.flush();
131 encodeULEB128(OutString.size(), OS);
132 OS << OutString;
Sam Clegg9e1ade92017-06-27 20:27:59 +0000133 OutString.clear();
134 }
135
Heejin Ahn18c56a02019-02-04 19:13:39 +0000136 raw_ostream &getStream() { return StringStream; }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000137};
138
Heejin Ahnf208f632018-09-05 01:27:38 +0000139int WasmWriter::writeSectionContent(raw_ostream &OS,
Sam Clegge4afbc62018-11-14 18:36:24 +0000140 WasmYAML::DylinkSection &Section) {
141 writeStringRef(Section.Name, OS);
142 encodeULEB128(Section.MemorySize, OS);
143 encodeULEB128(Section.MemoryAlignment, OS);
144 encodeULEB128(Section.TableSize, OS);
145 encodeULEB128(Section.TableAlignment, OS);
Sam Clegg03801252018-12-12 23:40:58 +0000146 encodeULEB128(Section.Needed.size(), OS);
147 for (StringRef Needed : Section.Needed) {
148 writeStringRef(Needed, OS);
149 }
Sam Clegge4afbc62018-11-14 18:36:24 +0000150 return 0;
151}
152
153int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnf208f632018-09-05 01:27:38 +0000154 WasmYAML::LinkingSection &Section) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000155 writeStringRef(Section.Name, OS);
Sam Clegg6bb5a412018-04-26 18:15:32 +0000156 encodeULEB128(Section.Version, OS);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000157
158 SubSectionWriter SubSection(OS);
159
Sam Clegg6c899ba2018-02-23 05:08:34 +0000160 // SYMBOL_TABLE subsection
161 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000162 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000163
Heejin Ahn18c56a02019-02-04 19:13:39 +0000164 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000165#ifndef NDEBUG
Sam Clegg6c899ba2018-02-23 05:08:34 +0000166 uint32_t SymbolIndex = 0;
167#endif
168 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
169 assert(Info.Index == SymbolIndex++);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000170 writeUint8(SubSection.getStream(), Info.Kind);
171 encodeULEB128(Info.Flags, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000172 switch (Info.Kind) {
173 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
174 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahnda419bd2018-11-14 02:46:21 +0000175 case wasm::WASM_SYMBOL_TYPE_EVENT:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000176 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Dan Gohman29874ce2019-02-07 22:03:32 +0000177 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
178 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Heejin Ahn18c56a02019-02-04 19:13:39 +0000179 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000180 break;
181 case wasm::WASM_SYMBOL_TYPE_DATA:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000182 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000183 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000184 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
185 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
186 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000187 }
188 break;
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000189 case wasm::WASM_SYMBOL_TYPE_SECTION:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000190 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000191 break;
Sam Clegg6c899ba2018-02-23 05:08:34 +0000192 default:
193 llvm_unreachable("unexpected kind");
194 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000195 }
196
Heejin Ahn18c56a02019-02-04 19:13:39 +0000197 SubSection.done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000198 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000199
200 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000201 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000202 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000203 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
Sam Clegg63ebb812017-09-29 16:50:08 +0000204 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000205 writeStringRef(SegmentInfo.Name, SubSection.getStream());
206 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
207 encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000208 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000209 SubSection.done();
Sam Cleggd95ed952017-09-20 19:03:35 +0000210 }
Sam Clegg42739982017-12-14 21:10:03 +0000211
212 // INIT_FUNCS subsection
213 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000214 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000215 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000216 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000217 encodeULEB128(Func.Priority, SubSection.getStream());
218 encodeULEB128(Func.Symbol, SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000219 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000220 SubSection.done();
Sam Clegg42739982017-12-14 21:10:03 +0000221 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000222
223 // COMDAT_INFO subsection
224 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000225 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000226 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000227 for (const auto &C : Section.Comdats) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000228 writeStringRef(C.Name, SubSection.getStream());
229 encodeULEB128(0, SubSection.getStream()); // flags for future use
230 encodeULEB128(C.Entries.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000231 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000232 writeUint8(SubSection.getStream(), Entry.Kind);
233 encodeULEB128(Entry.Index, SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000234 }
235 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000236 SubSection.done();
Sam Cleggea7cace2018-01-09 23:43:14 +0000237 }
238
Sam Cleggb7787fd2017-06-20 04:04:59 +0000239 return 0;
240}
241
Heejin Ahnf208f632018-09-05 01:27:38 +0000242int WasmWriter::writeSectionContent(raw_ostream &OS,
243 WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000244 writeStringRef(Section.Name, OS);
245 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000246 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000247
Sam Clegg9e1ade92017-06-27 20:27:59 +0000248 SubSectionWriter SubSection(OS);
249
Heejin Ahn18c56a02019-02-04 19:13:39 +0000250 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000251 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000252 encodeULEB128(NameEntry.Index, SubSection.getStream());
253 writeStringRef(NameEntry.Name, SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000254 }
255
Heejin Ahn18c56a02019-02-04 19:13:39 +0000256 SubSection.done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000257 }
258 return 0;
259}
260
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000261int WasmWriter::writeSectionContent(raw_ostream &OS,
Thomas Livelycbda16e2019-01-17 02:29:55 +0000262 WasmYAML::ProducersSection &Section) {
263 writeStringRef(Section.Name, OS);
264 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
265 int(!Section.SDKs.empty());
266 if (Fields == 0)
267 return 0;
268 encodeULEB128(Fields, OS);
269 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
270 std::make_pair(StringRef("processed-by"), &Section.Tools),
271 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
272 if (Field.second->empty())
273 continue;
274 writeStringRef(Field.first, OS);
275 encodeULEB128(Field.second->size(), OS);
276 for (auto &Entry : *Field.second) {
277 writeStringRef(Entry.Name, OS);
278 writeStringRef(Entry.Version, OS);
279 }
280 }
281 return 0;
282}
283
284int WasmWriter::writeSectionContent(raw_ostream &OS,
Thomas Livelyf6f4f842019-03-20 20:26:45 +0000285 WasmYAML::TargetFeaturesSection &Section) {
286 writeStringRef(Section.Name, OS);
287 encodeULEB128(Section.Features.size(), OS);
288 for (auto &E : Section.Features) {
289 writeUint8(OS, E.Prefix);
290 writeStringRef(E.Name, OS);
291 }
292 return 0;
293}
294
295int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000296 WasmYAML::CustomSection &Section) {
Sam Clegge4afbc62018-11-14 18:36:24 +0000297 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
298 if (auto Err = writeSectionContent(OS, *S))
299 return Err;
300 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
Sam Cleggb7787fd2017-06-20 04:04:59 +0000301 if (auto Err = writeSectionContent(OS, *S))
302 return Err;
303 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
304 if (auto Err = writeSectionContent(OS, *S))
305 return Err;
Thomas Livelycbda16e2019-01-17 02:29:55 +0000306 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
307 if (auto Err = writeSectionContent(OS, *S))
308 return Err;
Thomas Livelyf6f4f842019-03-20 20:26:45 +0000309 } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
310 if (auto Err = writeSectionContent(OS, *S))
311 return Err;
Sam Clegg03cdd122017-05-05 18:12:34 +0000312 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000313 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000314 Section.Payload.writeAsBinary(OS);
315 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000316 return 0;
317}
318
319int WasmWriter::writeSectionContent(raw_ostream &OS,
320 WasmYAML::TypeSection &Section) {
321 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000322 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000323 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000324 if (Sig.Index != ExpectedIndex) {
325 errs() << "Unexpected type index: " << Sig.Index << "\n";
326 return 1;
327 }
328 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000329 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000330 encodeULEB128(Sig.ParamTypes.size(), OS);
331 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000332 writeUint8(OS, ParamType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000333 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000334 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000335 } else {
336 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000337 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000338 }
339 }
340 return 0;
341}
342
343int WasmWriter::writeSectionContent(raw_ostream &OS,
344 WasmYAML::ImportSection &Section) {
345 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000346 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000347 writeStringRef(Import.Module, OS);
348 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000349 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000350 switch (Import.Kind) {
351 case wasm::WASM_EXTERNAL_FUNCTION:
352 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000353 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000354 break;
355 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000356 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000357 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000358 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000359 break;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000360 case wasm::WASM_EXTERNAL_EVENT:
361 writeUint32(OS, Import.EventImport.Attribute);
362 writeUint32(OS, Import.EventImport.SigIndex);
363 NumImportedGlobals++;
364 break;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000365 case wasm::WASM_EXTERNAL_MEMORY:
366 writeLimits(Import.Memory, OS);
367 break;
368 case wasm::WASM_EXTERNAL_TABLE:
Heejin Ahnf208f632018-09-05 01:27:38 +0000369 writeUint8(OS, Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000370 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000371 break;
372 default:
Sam Clegge53af7f2018-01-09 21:38:53 +0000373 errs() << "Unknown import type: " << Import.Kind << "\n";
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000374 return 1;
375 }
376 }
377 return 0;
378}
379
380int WasmWriter::writeSectionContent(raw_ostream &OS,
381 WasmYAML::FunctionSection &Section) {
382 encodeULEB128(Section.FunctionTypes.size(), OS);
383 for (uint32_t FuncType : Section.FunctionTypes) {
384 encodeULEB128(FuncType, OS);
385 }
386 return 0;
387}
388
389int WasmWriter::writeSectionContent(raw_ostream &OS,
390 WasmYAML::ExportSection &Section) {
391 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000392 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000393 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000394 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000395 encodeULEB128(Export.Index, OS);
396 }
397 return 0;
398}
399
400int WasmWriter::writeSectionContent(raw_ostream &OS,
401 WasmYAML::StartSection &Section) {
402 encodeULEB128(Section.StartFunction, OS);
403 return 0;
404}
405
406int WasmWriter::writeSectionContent(raw_ostream &OS,
407 WasmYAML::TableSection &Section) {
408 encodeULEB128(Section.Tables.size(), OS);
409 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000410 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000411 writeLimits(Table.TableLimits, OS);
412 }
413 return 0;
414}
415
416int WasmWriter::writeSectionContent(raw_ostream &OS,
417 WasmYAML::MemorySection &Section) {
418 encodeULEB128(Section.Memories.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000419 for (const WasmYAML::Limits &Mem : Section.Memories) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000420 writeLimits(Mem, OS);
421 }
422 return 0;
423}
424
425int WasmWriter::writeSectionContent(raw_ostream &OS,
426 WasmYAML::GlobalSection &Section) {
427 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000428 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000429 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000430 if (Global.Index != ExpectedIndex) {
431 errs() << "Unexpected global index: " << Global.Index << "\n";
432 return 1;
433 }
434 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000435 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000436 writeUint8(OS, Global.Mutable);
437 writeInitExpr(Global.InitExpr, OS);
438 }
439 return 0;
440}
441
442int WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnda419bd2018-11-14 02:46:21 +0000443 WasmYAML::EventSection &Section) {
444 encodeULEB128(Section.Events.size(), OS);
445 uint32_t ExpectedIndex = NumImportedEvents;
446 for (auto &Event : Section.Events) {
447 if (Event.Index != ExpectedIndex) {
448 errs() << "Unexpected event index: " << Event.Index << "\n";
449 return 1;
450 }
451 ++ExpectedIndex;
452 encodeULEB128(Event.Attribute, OS);
453 encodeULEB128(Event.SigIndex, OS);
454 }
455 return 0;
456}
457
458int WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000459 WasmYAML::ElemSection &Section) {
460 encodeULEB128(Section.Segments.size(), OS);
461 for (auto &Segment : Section.Segments) {
462 encodeULEB128(Segment.TableIndex, OS);
463 writeInitExpr(Segment.Offset, OS);
464
465 encodeULEB128(Segment.Functions.size(), OS);
466 for (auto &Function : Segment.Functions) {
467 encodeULEB128(Function, OS);
468 }
469 }
470 return 0;
471}
472
473int WasmWriter::writeSectionContent(raw_ostream &OS,
474 WasmYAML::CodeSection &Section) {
475 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000476 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000477 for (auto &Func : Section.Functions) {
478 std::string OutString;
479 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000480 if (Func.Index != ExpectedIndex) {
481 errs() << "Unexpected function index: " << Func.Index << "\n";
482 return 1;
483 }
484 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000485
486 encodeULEB128(Func.Locals.size(), StringStream);
487 for (auto &LocalDecl : Func.Locals) {
488 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000489 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000490 }
491
492 Func.Body.writeAsBinary(StringStream);
493
494 // Write the section size followed by the content
495 StringStream.flush();
496 encodeULEB128(OutString.size(), OS);
497 OS << OutString;
498 }
499 return 0;
500}
501
502int WasmWriter::writeSectionContent(raw_ostream &OS,
503 WasmYAML::DataSection &Section) {
504 encodeULEB128(Section.Segments.size(), OS);
505 for (auto &Segment : Section.Segments) {
Thomas Lively2e150402019-02-19 22:56:19 +0000506 encodeULEB128(Segment.InitFlags, OS);
507 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
508 encodeULEB128(Segment.MemoryIndex, OS);
509 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
510 writeInitExpr(Segment.Offset, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000511 encodeULEB128(Segment.Content.binary_size(), OS);
512 Segment.Content.writeAsBinary(OS);
513 }
514 return 0;
515}
516
Sam Clegg6f08c842018-04-24 18:11:36 +0000517int WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
518 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000519 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000520 case wasm::WASM_SEC_CODE:
521 writeStringRef("reloc.CODE", OS);
522 break;
523 case wasm::WASM_SEC_DATA:
524 writeStringRef("reloc.DATA", OS);
525 break;
526 case wasm::WASM_SEC_CUSTOM: {
527 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
528 if (!CustomSection->Name.startswith(".debug_")) {
529 llvm_unreachable("not yet implemented (only for debug sections)");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000530 return 1;
Heejin Ahnf208f632018-09-05 01:27:38 +0000531 }
532
533 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
534 break;
535 }
536 default:
537 llvm_unreachable("not yet implemented");
538 return 1;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000539 }
540
Sam Clegg6f08c842018-04-24 18:11:36 +0000541 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000542 encodeULEB128(Sec.Relocations.size(), OS);
543
Heejin Ahnf208f632018-09-05 01:27:38 +0000544 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000545 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000546 encodeULEB128(Reloc.Offset, OS);
547 encodeULEB128(Reloc.Index, OS);
548 switch (Reloc.Type) {
Sam Cleggd1152a22019-02-04 17:28:46 +0000549 case wasm::R_WASM_MEMORY_ADDR_LEB:
550 case wasm::R_WASM_MEMORY_ADDR_SLEB:
551 case wasm::R_WASM_MEMORY_ADDR_I32:
552 case wasm::R_WASM_FUNCTION_OFFSET_I32:
553 case wasm::R_WASM_SECTION_OFFSET_I32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000554 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000555 }
556 }
557 return 0;
558}
559
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000560int WasmWriter::writeWasm(raw_ostream &OS) {
561 // Write headers
562 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
563 writeUint32(OS, Obj.Header.Version);
564
565 // Write each section
Heejin Ahnfeef7202018-12-15 00:58:12 +0000566 llvm::object::WasmSectionOrderChecker Checker;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000567 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Heejin Ahnfeef7202018-12-15 00:58:12 +0000568 StringRef SecName = "";
569 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
570 SecName = S->Name;
571 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
572 errs() << "Out of order section type: " << Sec->Type << "\n";
573 return 1;
574 }
Sam Clegge53af7f2018-01-09 21:38:53 +0000575 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000576 std::string OutString;
577 raw_string_ostream StringStream(OutString);
578 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
579 if (auto Err = writeSectionContent(StringStream, *S))
580 return Err;
581 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
582 if (auto Err = writeSectionContent(StringStream, *S))
583 return Err;
584 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
585 if (auto Err = writeSectionContent(StringStream, *S))
586 return Err;
587 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
588 if (auto Err = writeSectionContent(StringStream, *S))
589 return Err;
590 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
591 if (auto Err = writeSectionContent(StringStream, *S))
592 return Err;
593 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
594 if (auto Err = writeSectionContent(StringStream, *S))
595 return Err;
596 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
597 if (auto Err = writeSectionContent(StringStream, *S))
598 return Err;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000599 } else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get())) {
600 if (auto Err = writeSectionContent(StringStream, *S))
601 return Err;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000602 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
603 if (auto Err = writeSectionContent(StringStream, *S))
604 return Err;
605 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
606 if (auto Err = writeSectionContent(StringStream, *S))
607 return Err;
608 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
609 if (auto Err = writeSectionContent(StringStream, *S))
610 return Err;
611 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
612 if (auto Err = writeSectionContent(StringStream, *S))
613 return Err;
614 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
615 if (auto Err = writeSectionContent(StringStream, *S))
616 return Err;
617 } else {
618 errs() << "Unknown section type: " << Sec->Type << "\n";
619 return 1;
620 }
621 StringStream.flush();
622
623 // Write the section size followed by the content
624 encodeULEB128(OutString.size(), OS);
625 OS << OutString;
626 }
627
628 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000629 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000630 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000631 if (Sec->Relocations.empty()) {
632 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000633 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000634 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000635
Sam Clegg03e101f2018-03-01 18:06:21 +0000636 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000637 std::string OutString;
638 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000639 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000640 StringStream.flush();
641
642 encodeULEB128(OutString.size(), OS);
643 OS << OutString;
644 }
645
646 return 0;
647}
648
649int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
650 WasmWriter Writer(Doc);
651
652 return Writer.writeWasm(Out);
653}