blob: debc040587a87fa9c9a625eeb608ce43bf52e65a [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"
Alex Brachetc22d9662019-08-07 02:44:49 +000017#include "llvm/ObjectYAML/yaml2obj.h"
Derek Schuffd3d84fd2017-03-30 19:44:09 +000018#include "llvm/Support/Endian.h"
19#include "llvm/Support/LEB128.h"
20
21using namespace llvm;
22
Alex Brachetc22d9662019-08-07 02:44:49 +000023namespace {
Derek Schuffd3d84fd2017-03-30 19:44:09 +000024/// This parses a yaml stream that represents a Wasm object file.
25/// See docs/yaml2obj for the yaml scheema.
26class WasmWriter {
27public:
George Rimar85011022019-09-13 16:00:16 +000028 WasmWriter(WasmYAML::Object &Obj, yaml::ErrorHandler EH)
29 : Obj(Obj), ErrHandler(EH) {}
George Rimar7da559f2019-09-13 09:12:38 +000030 bool writeWasm(raw_ostream &OS);
Sam Cleggb7787fd2017-06-20 04:04:59 +000031
32private:
George Rimar85011022019-09-13 16:00:16 +000033 void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
34 uint32_t SectionIndex);
Sam Clegg03cdd122017-05-05 18:12:34 +000035
George Rimar85011022019-09-13 16:00:16 +000036 void writeInitExpr(raw_ostream &OS, const wasm::WasmInitExpr &InitExpr);
37
38 void writeSectionContent(raw_ostream &OS, WasmYAML::CustomSection &Section);
39 void writeSectionContent(raw_ostream &OS, WasmYAML::TypeSection &Section);
40 void writeSectionContent(raw_ostream &OS, WasmYAML::ImportSection &Section);
41 void writeSectionContent(raw_ostream &OS, WasmYAML::FunctionSection &Section);
42 void writeSectionContent(raw_ostream &OS, WasmYAML::TableSection &Section);
43 void writeSectionContent(raw_ostream &OS, WasmYAML::MemorySection &Section);
44 void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &Section);
45 void writeSectionContent(raw_ostream &OS, WasmYAML::EventSection &Section);
46 void writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
47 void writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
48 void writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
49 void writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
50 void writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
51 void writeSectionContent(raw_ostream &OS, WasmYAML::DataCountSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000052
Sam Cleggb7787fd2017-06-20 04:04:59 +000053 // Custom section types
George Rimar85011022019-09-13 16:00:16 +000054 void writeSectionContent(raw_ostream &OS, WasmYAML::DylinkSection &Section);
55 void writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
56 void writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
57 void writeSectionContent(raw_ostream &OS, WasmYAML::ProducersSection &Section);
58 void writeSectionContent(raw_ostream &OS,
Thomas Livelyf6f4f842019-03-20 20:26:45 +000059 WasmYAML::TargetFeaturesSection &Section);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000060 WasmYAML::Object &Obj;
Sam Clegge53af7f2018-01-09 21:38:53 +000061 uint32_t NumImportedFunctions = 0;
62 uint32_t NumImportedGlobals = 0;
Heejin Ahnda419bd2018-11-14 02:46:21 +000063 uint32_t NumImportedEvents = 0;
George Rimar85011022019-09-13 16:00:16 +000064
65 bool HasError = false;
66 yaml::ErrorHandler ErrHandler;
67 void reportError(const Twine &Msg);
Derek Schuffd3d84fd2017-03-30 19:44:09 +000068};
69
Alex Brachetc22d9662019-08-07 02:44:49 +000070class SubSectionWriter {
71 raw_ostream &OS;
72 std::string OutString;
73 raw_string_ostream StringStream;
74
75public:
76 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
77
78 void done() {
79 StringStream.flush();
80 encodeULEB128(OutString.size(), OS);
81 OS << OutString;
82 OutString.clear();
83 }
84
85 raw_ostream &getStream() { return StringStream; }
86};
87
88} // end anonymous namespace
89
Derek Schuffd3d84fd2017-03-30 19:44:09 +000090static int writeUint64(raw_ostream &OS, uint64_t Value) {
91 char Data[sizeof(Value)];
92 support::endian::write64le(Data, Value);
93 OS.write(Data, sizeof(Data));
94 return 0;
95}
96
97static int writeUint32(raw_ostream &OS, uint32_t Value) {
98 char Data[sizeof(Value)];
99 support::endian::write32le(Data, Value);
100 OS.write(Data, sizeof(Data));
101 return 0;
102}
103
104static int writeUint8(raw_ostream &OS, uint8_t Value) {
105 char Data[sizeof(Value)];
106 memcpy(Data, &Value, sizeof(Data));
107 OS.write(Data, sizeof(Data));
108 return 0;
109}
110
Sam Clegg03cdd122017-05-05 18:12:34 +0000111static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000112 encodeULEB128(Str.size(), OS);
113 OS << Str;
114 return 0;
115}
116
Sam Clegg03cdd122017-05-05 18:12:34 +0000117static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000118 writeUint8(OS, Lim.Flags);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000119 encodeULEB128(Lim.Initial, OS);
120 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
121 encodeULEB128(Lim.Maximum, OS);
122 return 0;
123}
124
George Rimar85011022019-09-13 16:00:16 +0000125void WasmWriter::reportError(const Twine &Msg) {
126 ErrHandler(Msg);
127 HasError = true;
128}
129
130void WasmWriter::writeInitExpr(raw_ostream &OS,
131 const wasm::WasmInitExpr &InitExpr) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000132 writeUint8(OS, InitExpr.Opcode);
133 switch (InitExpr.Opcode) {
134 case wasm::WASM_OPCODE_I32_CONST:
135 encodeSLEB128(InitExpr.Value.Int32, OS);
136 break;
137 case wasm::WASM_OPCODE_I64_CONST:
138 encodeSLEB128(InitExpr.Value.Int64, OS);
139 break;
140 case wasm::WASM_OPCODE_F32_CONST:
141 writeUint32(OS, InitExpr.Value.Float32);
142 break;
143 case wasm::WASM_OPCODE_F64_CONST:
144 writeUint64(OS, InitExpr.Value.Float64);
145 break;
Thomas Lively6a87dda2019-01-08 06:25:55 +0000146 case wasm::WASM_OPCODE_GLOBAL_GET:
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000147 encodeULEB128(InitExpr.Value.Global, OS);
148 break;
149 default:
George Rimar85011022019-09-13 16:00:16 +0000150 reportError("unknown opcode in init_expr: " + Twine(InitExpr.Opcode));
151 return;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000152 }
153 writeUint8(OS, wasm::WASM_OPCODE_END);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000154}
155
George Rimar85011022019-09-13 16:00:16 +0000156void WasmWriter::writeSectionContent(raw_ostream &OS,
157 WasmYAML::DylinkSection &Section) {
Sam Clegge4afbc62018-11-14 18:36:24 +0000158 writeStringRef(Section.Name, OS);
159 encodeULEB128(Section.MemorySize, OS);
160 encodeULEB128(Section.MemoryAlignment, OS);
161 encodeULEB128(Section.TableSize, OS);
162 encodeULEB128(Section.TableAlignment, OS);
Sam Clegg03801252018-12-12 23:40:58 +0000163 encodeULEB128(Section.Needed.size(), OS);
George Rimar85011022019-09-13 16:00:16 +0000164 for (StringRef Needed : Section.Needed)
Sam Clegg03801252018-12-12 23:40:58 +0000165 writeStringRef(Needed, OS);
Sam Clegge4afbc62018-11-14 18:36:24 +0000166}
167
George Rimar85011022019-09-13 16:00:16 +0000168void WasmWriter::writeSectionContent(raw_ostream &OS,
169 WasmYAML::LinkingSection &Section) {
Sam Clegg9e1ade92017-06-27 20:27:59 +0000170 writeStringRef(Section.Name, OS);
Sam Clegg6bb5a412018-04-26 18:15:32 +0000171 encodeULEB128(Section.Version, OS);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000172
173 SubSectionWriter SubSection(OS);
174
Sam Clegg6c899ba2018-02-23 05:08:34 +0000175 // SYMBOL_TABLE subsection
176 if (Section.SymbolTable.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000177 writeUint8(OS, wasm::WASM_SYMBOL_TABLE);
Sam Clegg9e1ade92017-06-27 20:27:59 +0000178
Heejin Ahn18c56a02019-02-04 19:13:39 +0000179 encodeULEB128(Section.SymbolTable.size(), SubSection.getStream());
Benjamin Kramer8d71fdc2018-02-23 12:20:18 +0000180#ifndef NDEBUG
Sam Clegg6c899ba2018-02-23 05:08:34 +0000181 uint32_t SymbolIndex = 0;
182#endif
183 for (const WasmYAML::SymbolInfo &Info : Section.SymbolTable) {
184 assert(Info.Index == SymbolIndex++);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000185 writeUint8(SubSection.getStream(), Info.Kind);
186 encodeULEB128(Info.Flags, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000187 switch (Info.Kind) {
188 case wasm::WASM_SYMBOL_TYPE_FUNCTION:
189 case wasm::WASM_SYMBOL_TYPE_GLOBAL:
Heejin Ahnda419bd2018-11-14 02:46:21 +0000190 case wasm::WASM_SYMBOL_TYPE_EVENT:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000191 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Dan Gohman29874ce2019-02-07 22:03:32 +0000192 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
193 (Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
Heejin Ahn18c56a02019-02-04 19:13:39 +0000194 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000195 break;
196 case wasm::WASM_SYMBOL_TYPE_DATA:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000197 writeStringRef(Info.Name, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000198 if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000199 encodeULEB128(Info.DataRef.Segment, SubSection.getStream());
200 encodeULEB128(Info.DataRef.Offset, SubSection.getStream());
201 encodeULEB128(Info.DataRef.Size, SubSection.getStream());
Sam Clegg6c899ba2018-02-23 05:08:34 +0000202 }
203 break;
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000204 case wasm::WASM_SYMBOL_TYPE_SECTION:
Heejin Ahn18c56a02019-02-04 19:13:39 +0000205 encodeULEB128(Info.ElementIndex, SubSection.getStream());
Sam Clegg6a31a0d2018-04-26 19:27:28 +0000206 break;
Sam Clegg6c899ba2018-02-23 05:08:34 +0000207 default:
208 llvm_unreachable("unexpected kind");
209 }
Sam Clegg9e1ade92017-06-27 20:27:59 +0000210 }
211
Heejin Ahn18c56a02019-02-04 19:13:39 +0000212 SubSection.done();
Sam Cleggb7787fd2017-06-20 04:04:59 +0000213 }
Sam Cleggd95ed952017-09-20 19:03:35 +0000214
215 // SEGMENT_NAMES subsection
Sam Clegg63ebb812017-09-29 16:50:08 +0000216 if (Section.SegmentInfos.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000217 writeUint8(OS, wasm::WASM_SEGMENT_INFO);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000218 encodeULEB128(Section.SegmentInfos.size(), SubSection.getStream());
Sam Clegg63ebb812017-09-29 16:50:08 +0000219 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000220 writeStringRef(SegmentInfo.Name, SubSection.getStream());
221 encodeULEB128(SegmentInfo.Alignment, SubSection.getStream());
222 encodeULEB128(SegmentInfo.Flags, SubSection.getStream());
Sam Cleggd95ed952017-09-20 19:03:35 +0000223 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000224 SubSection.done();
Sam Cleggd95ed952017-09-20 19:03:35 +0000225 }
Sam Clegg42739982017-12-14 21:10:03 +0000226
227 // INIT_FUNCS subsection
228 if (Section.InitFunctions.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000229 writeUint8(OS, wasm::WASM_INIT_FUNCS);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000230 encodeULEB128(Section.InitFunctions.size(), SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000231 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000232 encodeULEB128(Func.Priority, SubSection.getStream());
233 encodeULEB128(Func.Symbol, SubSection.getStream());
Sam Clegg42739982017-12-14 21:10:03 +0000234 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000235 SubSection.done();
Sam Clegg42739982017-12-14 21:10:03 +0000236 }
Sam Cleggea7cace2018-01-09 23:43:14 +0000237
238 // COMDAT_INFO subsection
239 if (Section.Comdats.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000240 writeUint8(OS, wasm::WASM_COMDAT_INFO);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000241 encodeULEB128(Section.Comdats.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000242 for (const auto &C : Section.Comdats) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000243 writeStringRef(C.Name, SubSection.getStream());
244 encodeULEB128(0, SubSection.getStream()); // flags for future use
245 encodeULEB128(C.Entries.size(), SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000246 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000247 writeUint8(SubSection.getStream(), Entry.Kind);
248 encodeULEB128(Entry.Index, SubSection.getStream());
Sam Cleggea7cace2018-01-09 23:43:14 +0000249 }
250 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000251 SubSection.done();
Sam Cleggea7cace2018-01-09 23:43:14 +0000252 }
Sam Cleggb7787fd2017-06-20 04:04:59 +0000253}
254
George Rimar85011022019-09-13 16:00:16 +0000255void WasmWriter::writeSectionContent(raw_ostream &OS,
256 WasmYAML::NameSection &Section) {
Sam Clegg03cdd122017-05-05 18:12:34 +0000257 writeStringRef(Section.Name, OS);
258 if (Section.FunctionNames.size()) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000259 writeUint8(OS, wasm::WASM_NAMES_FUNCTION);
Sam Clegg03cdd122017-05-05 18:12:34 +0000260
Sam Clegg9e1ade92017-06-27 20:27:59 +0000261 SubSectionWriter SubSection(OS);
262
Heejin Ahn18c56a02019-02-04 19:13:39 +0000263 encodeULEB128(Section.FunctionNames.size(), SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000264 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000265 encodeULEB128(NameEntry.Index, SubSection.getStream());
266 writeStringRef(NameEntry.Name, SubSection.getStream());
Sam Clegg03cdd122017-05-05 18:12:34 +0000267 }
268
Heejin Ahn18c56a02019-02-04 19:13:39 +0000269 SubSection.done();
Sam Clegg03cdd122017-05-05 18:12:34 +0000270 }
Sam Clegg03cdd122017-05-05 18:12:34 +0000271}
272
George Rimar85011022019-09-13 16:00:16 +0000273void WasmWriter::writeSectionContent(raw_ostream &OS,
274 WasmYAML::ProducersSection &Section) {
Thomas Livelycbda16e2019-01-17 02:29:55 +0000275 writeStringRef(Section.Name, OS);
276 int Fields = int(!Section.Languages.empty()) + int(!Section.Tools.empty()) +
277 int(!Section.SDKs.empty());
278 if (Fields == 0)
George Rimar85011022019-09-13 16:00:16 +0000279 return;
Thomas Livelycbda16e2019-01-17 02:29:55 +0000280 encodeULEB128(Fields, OS);
281 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
282 std::make_pair(StringRef("processed-by"), &Section.Tools),
283 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
284 if (Field.second->empty())
285 continue;
286 writeStringRef(Field.first, OS);
287 encodeULEB128(Field.second->size(), OS);
288 for (auto &Entry : *Field.second) {
289 writeStringRef(Entry.Name, OS);
290 writeStringRef(Entry.Version, OS);
291 }
292 }
Thomas Livelycbda16e2019-01-17 02:29:55 +0000293}
294
George Rimar85011022019-09-13 16:00:16 +0000295void WasmWriter::writeSectionContent(raw_ostream &OS,
296 WasmYAML::TargetFeaturesSection &Section) {
Thomas Livelyf6f4f842019-03-20 20:26:45 +0000297 writeStringRef(Section.Name, OS);
298 encodeULEB128(Section.Features.size(), OS);
299 for (auto &E : Section.Features) {
300 writeUint8(OS, E.Prefix);
301 writeStringRef(E.Name, OS);
302 }
Thomas Livelyf6f4f842019-03-20 20:26:45 +0000303}
304
George Rimar85011022019-09-13 16:00:16 +0000305void WasmWriter::writeSectionContent(raw_ostream &OS,
306 WasmYAML::CustomSection &Section) {
Sam Clegge4afbc62018-11-14 18:36:24 +0000307 if (auto S = dyn_cast<WasmYAML::DylinkSection>(&Section)) {
George Rimar85011022019-09-13 16:00:16 +0000308 writeSectionContent(OS, *S);
Sam Clegge4afbc62018-11-14 18:36:24 +0000309 } else if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
George Rimar85011022019-09-13 16:00:16 +0000310 writeSectionContent(OS, *S);
Sam Cleggb7787fd2017-06-20 04:04:59 +0000311 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
George Rimar85011022019-09-13 16:00:16 +0000312 writeSectionContent(OS, *S);
Thomas Livelycbda16e2019-01-17 02:29:55 +0000313 } else if (auto S = dyn_cast<WasmYAML::ProducersSection>(&Section)) {
George Rimar85011022019-09-13 16:00:16 +0000314 writeSectionContent(OS, *S);
Thomas Livelyf6f4f842019-03-20 20:26:45 +0000315 } else if (auto S = dyn_cast<WasmYAML::TargetFeaturesSection>(&Section)) {
George Rimar85011022019-09-13 16:00:16 +0000316 writeSectionContent(OS, *S);
Sam Clegg03cdd122017-05-05 18:12:34 +0000317 } else {
Sam Clegg9745afa2018-04-12 20:31:12 +0000318 writeStringRef(Section.Name, OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000319 Section.Payload.writeAsBinary(OS);
320 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000321}
322
George Rimar85011022019-09-13 16:00:16 +0000323void WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000324 WasmYAML::TypeSection &Section) {
325 encodeULEB128(Section.Signatures.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000326 uint32_t ExpectedIndex = 0;
Sam Clegg03cdd122017-05-05 18:12:34 +0000327 for (const WasmYAML::Signature &Sig : Section.Signatures) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000328 if (Sig.Index != ExpectedIndex) {
George Rimar85011022019-09-13 16:00:16 +0000329 reportError("unexpected type index: " + Twine(Sig.Index));
330 return;
Sam Clegge53af7f2018-01-09 21:38:53 +0000331 }
332 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000333 writeUint8(OS, Sig.Form);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000334 encodeULEB128(Sig.ParamTypes.size(), OS);
335 for (auto ParamType : Sig.ParamTypes)
Sam Clegg03e101f2018-03-01 18:06:21 +0000336 writeUint8(OS, ParamType);
Thomas Lively393d0f72019-10-18 20:27:30 +0000337 encodeULEB128(Sig.ReturnTypes.size(), OS);
338 for (auto ReturnType : Sig.ReturnTypes)
339 writeUint8(OS, ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000340 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000341}
342
George Rimar85011022019-09-13 16:00:16 +0000343void WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000344 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:
George Rimar85011022019-09-13 16:00:16 +0000373 reportError("unknown import type: " +Twine(Import.Kind));
374 return;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000375 }
376 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000377}
378
George Rimar85011022019-09-13 16:00:16 +0000379void WasmWriter::writeSectionContent(raw_ostream &OS,
380 WasmYAML::FunctionSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000381 encodeULEB128(Section.FunctionTypes.size(), OS);
George Rimar85011022019-09-13 16:00:16 +0000382 for (uint32_t FuncType : Section.FunctionTypes)
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000383 encodeULEB128(FuncType, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000384}
385
George Rimar85011022019-09-13 16:00:16 +0000386void WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000387 WasmYAML::ExportSection &Section) {
388 encodeULEB128(Section.Exports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000389 for (const WasmYAML::Export &Export : Section.Exports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000390 writeStringRef(Export.Name, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000391 writeUint8(OS, Export.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000392 encodeULEB128(Export.Index, OS);
393 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000394}
395
George Rimar85011022019-09-13 16:00:16 +0000396void WasmWriter::writeSectionContent(raw_ostream &OS,
397 WasmYAML::StartSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000398 encodeULEB128(Section.StartFunction, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000399}
400
George Rimar85011022019-09-13 16:00:16 +0000401void WasmWriter::writeSectionContent(raw_ostream &OS,
402 WasmYAML::TableSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000403 encodeULEB128(Section.Tables.size(), OS);
404 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000405 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000406 writeLimits(Table.TableLimits, OS);
407 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000408}
409
George Rimar85011022019-09-13 16:00:16 +0000410void WasmWriter::writeSectionContent(raw_ostream &OS,
411 WasmYAML::MemorySection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000412 encodeULEB128(Section.Memories.size(), OS);
George Rimar85011022019-09-13 16:00:16 +0000413 for (const WasmYAML::Limits &Mem : Section.Memories)
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000414 writeLimits(Mem, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000415}
416
George Rimar85011022019-09-13 16:00:16 +0000417void WasmWriter::writeSectionContent(raw_ostream &OS,
418 WasmYAML::GlobalSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000419 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000420 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000421 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000422 if (Global.Index != ExpectedIndex) {
George Rimar85011022019-09-13 16:00:16 +0000423 reportError("unexpected global index: " + Twine(Global.Index));
424 return;
Sam Clegge53af7f2018-01-09 21:38:53 +0000425 }
426 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000427 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000428 writeUint8(OS, Global.Mutable);
George Rimar85011022019-09-13 16:00:16 +0000429 writeInitExpr(OS, Global.InitExpr);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000430 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000431}
432
George Rimar85011022019-09-13 16:00:16 +0000433void WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnda419bd2018-11-14 02:46:21 +0000434 WasmYAML::EventSection &Section) {
435 encodeULEB128(Section.Events.size(), OS);
436 uint32_t ExpectedIndex = NumImportedEvents;
437 for (auto &Event : Section.Events) {
438 if (Event.Index != ExpectedIndex) {
George Rimar85011022019-09-13 16:00:16 +0000439 reportError("unexpected event index: " + Twine(Event.Index));
440 return;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000441 }
442 ++ExpectedIndex;
443 encodeULEB128(Event.Attribute, OS);
444 encodeULEB128(Event.SigIndex, OS);
445 }
Heejin Ahnda419bd2018-11-14 02:46:21 +0000446}
447
George Rimar85011022019-09-13 16:00:16 +0000448void WasmWriter::writeSectionContent(raw_ostream &OS,
449 WasmYAML::ElemSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000450 encodeULEB128(Section.Segments.size(), OS);
451 for (auto &Segment : Section.Segments) {
452 encodeULEB128(Segment.TableIndex, OS);
George Rimar85011022019-09-13 16:00:16 +0000453 writeInitExpr(OS, Segment.Offset);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000454
455 encodeULEB128(Segment.Functions.size(), OS);
George Rimar85011022019-09-13 16:00:16 +0000456 for (auto &Function : Segment.Functions)
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000457 encodeULEB128(Function, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000458 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000459}
460
George Rimar85011022019-09-13 16:00:16 +0000461void WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000462 WasmYAML::CodeSection &Section) {
463 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000464 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000465 for (auto &Func : Section.Functions) {
466 std::string OutString;
467 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000468 if (Func.Index != ExpectedIndex) {
George Rimar85011022019-09-13 16:00:16 +0000469 reportError("unexpected function index: " + Twine(Func.Index));
470 return;
Sam Clegge53af7f2018-01-09 21:38:53 +0000471 }
472 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000473
474 encodeULEB128(Func.Locals.size(), StringStream);
475 for (auto &LocalDecl : Func.Locals) {
476 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000477 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000478 }
479
480 Func.Body.writeAsBinary(StringStream);
481
482 // Write the section size followed by the content
483 StringStream.flush();
484 encodeULEB128(OutString.size(), OS);
485 OS << OutString;
486 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000487}
488
George Rimar85011022019-09-13 16:00:16 +0000489void WasmWriter::writeSectionContent(raw_ostream &OS,
490 WasmYAML::DataSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000491 encodeULEB128(Section.Segments.size(), OS);
492 for (auto &Segment : Section.Segments) {
Thomas Lively2e150402019-02-19 22:56:19 +0000493 encodeULEB128(Segment.InitFlags, OS);
494 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
495 encodeULEB128(Segment.MemoryIndex, OS);
496 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
George Rimar85011022019-09-13 16:00:16 +0000497 writeInitExpr(OS, Segment.Offset);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000498 encodeULEB128(Segment.Content.binary_size(), OS);
499 Segment.Content.writeAsBinary(OS);
500 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000501}
502
George Rimar85011022019-09-13 16:00:16 +0000503void WasmWriter::writeSectionContent(raw_ostream &OS,
504 WasmYAML::DataCountSection &Section) {
Thomas Livelyfef8de62019-04-12 22:27:48 +0000505 encodeULEB128(Section.Count, OS);
Thomas Livelyfef8de62019-04-12 22:27:48 +0000506}
507
George Rimar85011022019-09-13 16:00:16 +0000508void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
Sam Clegg6f08c842018-04-24 18:11:36 +0000509 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000510 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000511 case wasm::WASM_SEC_CODE:
512 writeStringRef("reloc.CODE", OS);
513 break;
514 case wasm::WASM_SEC_DATA:
515 writeStringRef("reloc.DATA", OS);
516 break;
517 case wasm::WASM_SEC_CUSTOM: {
Simon Pilgrim6e1a9b02019-09-17 19:14:11 +0000518 auto *CustomSection = cast<WasmYAML::CustomSection>(&Sec);
Heejin Ahnf208f632018-09-05 01:27:38 +0000519 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
520 break;
521 }
522 default:
523 llvm_unreachable("not yet implemented");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000524 }
525
Sam Clegg6f08c842018-04-24 18:11:36 +0000526 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000527 encodeULEB128(Sec.Relocations.size(), OS);
528
Heejin Ahnf208f632018-09-05 01:27:38 +0000529 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000530 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000531 encodeULEB128(Reloc.Offset, OS);
532 encodeULEB128(Reloc.Index, OS);
533 switch (Reloc.Type) {
Sam Cleggd1152a22019-02-04 17:28:46 +0000534 case wasm::R_WASM_MEMORY_ADDR_LEB:
535 case wasm::R_WASM_MEMORY_ADDR_SLEB:
536 case wasm::R_WASM_MEMORY_ADDR_I32:
537 case wasm::R_WASM_FUNCTION_OFFSET_I32:
538 case wasm::R_WASM_SECTION_OFFSET_I32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000539 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000540 }
541 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000542}
543
George Rimar7da559f2019-09-13 09:12:38 +0000544bool WasmWriter::writeWasm(raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000545 // 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)) {
George Rimar85011022019-09-13 16:00:16 +0000556 reportError("out of order section type: " + Twine(Sec->Type));
George Rimar7da559f2019-09-13 09:12:38 +0000557 return false;
Heejin Ahnfeef7202018-12-15 00:58:12 +0000558 }
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);
George Rimar85011022019-09-13 16:00:16 +0000562 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
563 writeSectionContent(StringStream, *S);
564 else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
565 writeSectionContent(StringStream, *S);
566 else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
567 writeSectionContent(StringStream, *S);
568 else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
569 writeSectionContent(StringStream, *S);
570 else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
571 writeSectionContent(StringStream, *S);
572 else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
573 writeSectionContent(StringStream, *S);
574 else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
575 writeSectionContent(StringStream, *S);
576 else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get()))
577 writeSectionContent(StringStream, *S);
578 else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
579 writeSectionContent(StringStream, *S);
580 else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
581 writeSectionContent(StringStream, *S);
582 else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
583 writeSectionContent(StringStream, *S);
584 else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
585 writeSectionContent(StringStream, *S);
586 else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
587 writeSectionContent(StringStream, *S);
588 else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
589 writeSectionContent(StringStream, *S);
590 else
591 reportError("unknown section type: " + Twine(Sec->Type));
592
593 if (HasError)
George Rimar7da559f2019-09-13 09:12:38 +0000594 return false;
George Rimar85011022019-09-13 16:00:16 +0000595
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000596 StringStream.flush();
597
598 // Write the section size followed by the content
599 encodeULEB128(OutString.size(), OS);
600 OS << OutString;
601 }
602
603 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000604 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000605 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000606 if (Sec->Relocations.empty()) {
607 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000608 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000609 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000610
Sam Clegg03e101f2018-03-01 18:06:21 +0000611 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000612 std::string OutString;
613 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000614 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000615 StringStream.flush();
616
617 encodeULEB128(OutString.size(), OS);
618 OS << OutString;
619 }
620
George Rimar7da559f2019-09-13 09:12:38 +0000621 return true;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000622}
623
Alex Brachetc22d9662019-08-07 02:44:49 +0000624namespace llvm {
625namespace yaml {
626
George Rimar85011022019-09-13 16:00:16 +0000627bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
628 WasmWriter Writer(Doc, EH);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000629 return Writer.writeWasm(Out);
630}
Alex Brachetc22d9662019-08-07 02:44:49 +0000631
632} // namespace yaml
633} // namespace llvm