blob: e374764bf13962b21e276a41fa5760472c8a58ab [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);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000337 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000338 encodeULEB128(0, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000339 } else {
340 encodeULEB128(1, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000341 writeUint8(OS, Sig.ReturnType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000342 }
343 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000344}
345
George Rimar85011022019-09-13 16:00:16 +0000346void WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000347 WasmYAML::ImportSection &Section) {
348 encodeULEB128(Section.Imports.size(), OS);
Sam Clegg03cdd122017-05-05 18:12:34 +0000349 for (const WasmYAML::Import &Import : Section.Imports) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000350 writeStringRef(Import.Module, OS);
351 writeStringRef(Import.Field, OS);
Sam Clegg03e101f2018-03-01 18:06:21 +0000352 writeUint8(OS, Import.Kind);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000353 switch (Import.Kind) {
354 case wasm::WASM_EXTERNAL_FUNCTION:
355 encodeULEB128(Import.SigIndex, OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000356 NumImportedFunctions++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000357 break;
358 case wasm::WASM_EXTERNAL_GLOBAL:
Sam Clegg03e101f2018-03-01 18:06:21 +0000359 writeUint8(OS, Import.GlobalImport.Type);
Sam Clegg41db5192017-05-10 00:14:04 +0000360 writeUint8(OS, Import.GlobalImport.Mutable);
Sam Clegge53af7f2018-01-09 21:38:53 +0000361 NumImportedGlobals++;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000362 break;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000363 case wasm::WASM_EXTERNAL_EVENT:
364 writeUint32(OS, Import.EventImport.Attribute);
365 writeUint32(OS, Import.EventImport.SigIndex);
366 NumImportedGlobals++;
367 break;
Sam Clegg2ffff5a2017-05-09 23:48:41 +0000368 case wasm::WASM_EXTERNAL_MEMORY:
369 writeLimits(Import.Memory, OS);
370 break;
371 case wasm::WASM_EXTERNAL_TABLE:
Heejin Ahnf208f632018-09-05 01:27:38 +0000372 writeUint8(OS, Import.TableImport.ElemType);
Sam Clegg41db5192017-05-10 00:14:04 +0000373 writeLimits(Import.TableImport.TableLimits, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000374 break;
375 default:
George Rimar85011022019-09-13 16:00:16 +0000376 reportError("unknown import type: " +Twine(Import.Kind));
377 return;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000378 }
379 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000380}
381
George Rimar85011022019-09-13 16:00:16 +0000382void WasmWriter::writeSectionContent(raw_ostream &OS,
383 WasmYAML::FunctionSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000384 encodeULEB128(Section.FunctionTypes.size(), OS);
George Rimar85011022019-09-13 16:00:16 +0000385 for (uint32_t FuncType : Section.FunctionTypes)
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000386 encodeULEB128(FuncType, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000387}
388
George Rimar85011022019-09-13 16:00:16 +0000389void WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000390 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 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000397}
398
George Rimar85011022019-09-13 16:00:16 +0000399void WasmWriter::writeSectionContent(raw_ostream &OS,
400 WasmYAML::StartSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000401 encodeULEB128(Section.StartFunction, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000402}
403
George Rimar85011022019-09-13 16:00:16 +0000404void WasmWriter::writeSectionContent(raw_ostream &OS,
405 WasmYAML::TableSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000406 encodeULEB128(Section.Tables.size(), OS);
407 for (auto &Table : Section.Tables) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000408 writeUint8(OS, Table.ElemType);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000409 writeLimits(Table.TableLimits, OS);
410 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000411}
412
George Rimar85011022019-09-13 16:00:16 +0000413void WasmWriter::writeSectionContent(raw_ostream &OS,
414 WasmYAML::MemorySection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000415 encodeULEB128(Section.Memories.size(), OS);
George Rimar85011022019-09-13 16:00:16 +0000416 for (const WasmYAML::Limits &Mem : Section.Memories)
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000417 writeLimits(Mem, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000418}
419
George Rimar85011022019-09-13 16:00:16 +0000420void WasmWriter::writeSectionContent(raw_ostream &OS,
421 WasmYAML::GlobalSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000422 encodeULEB128(Section.Globals.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000423 uint32_t ExpectedIndex = NumImportedGlobals;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000424 for (auto &Global : Section.Globals) {
Sam Clegge53af7f2018-01-09 21:38:53 +0000425 if (Global.Index != ExpectedIndex) {
George Rimar85011022019-09-13 16:00:16 +0000426 reportError("unexpected global index: " + Twine(Global.Index));
427 return;
Sam Clegge53af7f2018-01-09 21:38:53 +0000428 }
429 ++ExpectedIndex;
Sam Clegg03e101f2018-03-01 18:06:21 +0000430 writeUint8(OS, Global.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000431 writeUint8(OS, Global.Mutable);
George Rimar85011022019-09-13 16:00:16 +0000432 writeInitExpr(OS, Global.InitExpr);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000433 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000434}
435
George Rimar85011022019-09-13 16:00:16 +0000436void WasmWriter::writeSectionContent(raw_ostream &OS,
Heejin Ahnda419bd2018-11-14 02:46:21 +0000437 WasmYAML::EventSection &Section) {
438 encodeULEB128(Section.Events.size(), OS);
439 uint32_t ExpectedIndex = NumImportedEvents;
440 for (auto &Event : Section.Events) {
441 if (Event.Index != ExpectedIndex) {
George Rimar85011022019-09-13 16:00:16 +0000442 reportError("unexpected event index: " + Twine(Event.Index));
443 return;
Heejin Ahnda419bd2018-11-14 02:46:21 +0000444 }
445 ++ExpectedIndex;
446 encodeULEB128(Event.Attribute, OS);
447 encodeULEB128(Event.SigIndex, OS);
448 }
Heejin Ahnda419bd2018-11-14 02:46:21 +0000449}
450
George Rimar85011022019-09-13 16:00:16 +0000451void WasmWriter::writeSectionContent(raw_ostream &OS,
452 WasmYAML::ElemSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000453 encodeULEB128(Section.Segments.size(), OS);
454 for (auto &Segment : Section.Segments) {
455 encodeULEB128(Segment.TableIndex, OS);
George Rimar85011022019-09-13 16:00:16 +0000456 writeInitExpr(OS, Segment.Offset);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000457
458 encodeULEB128(Segment.Functions.size(), OS);
George Rimar85011022019-09-13 16:00:16 +0000459 for (auto &Function : Segment.Functions)
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000460 encodeULEB128(Function, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000461 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000462}
463
George Rimar85011022019-09-13 16:00:16 +0000464void WasmWriter::writeSectionContent(raw_ostream &OS,
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000465 WasmYAML::CodeSection &Section) {
466 encodeULEB128(Section.Functions.size(), OS);
Sam Clegge53af7f2018-01-09 21:38:53 +0000467 uint32_t ExpectedIndex = NumImportedFunctions;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000468 for (auto &Func : Section.Functions) {
469 std::string OutString;
470 raw_string_ostream StringStream(OutString);
Sam Clegge53af7f2018-01-09 21:38:53 +0000471 if (Func.Index != ExpectedIndex) {
George Rimar85011022019-09-13 16:00:16 +0000472 reportError("unexpected function index: " + Twine(Func.Index));
473 return;
Sam Clegge53af7f2018-01-09 21:38:53 +0000474 }
475 ++ExpectedIndex;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000476
477 encodeULEB128(Func.Locals.size(), StringStream);
478 for (auto &LocalDecl : Func.Locals) {
479 encodeULEB128(LocalDecl.Count, StringStream);
Sam Clegg03e101f2018-03-01 18:06:21 +0000480 writeUint8(StringStream, LocalDecl.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000481 }
482
483 Func.Body.writeAsBinary(StringStream);
484
485 // Write the section size followed by the content
486 StringStream.flush();
487 encodeULEB128(OutString.size(), OS);
488 OS << OutString;
489 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000490}
491
George Rimar85011022019-09-13 16:00:16 +0000492void WasmWriter::writeSectionContent(raw_ostream &OS,
493 WasmYAML::DataSection &Section) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000494 encodeULEB128(Section.Segments.size(), OS);
495 for (auto &Segment : Section.Segments) {
Thomas Lively2e150402019-02-19 22:56:19 +0000496 encodeULEB128(Segment.InitFlags, OS);
497 if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
498 encodeULEB128(Segment.MemoryIndex, OS);
499 if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0)
George Rimar85011022019-09-13 16:00:16 +0000500 writeInitExpr(OS, Segment.Offset);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000501 encodeULEB128(Segment.Content.binary_size(), OS);
502 Segment.Content.writeAsBinary(OS);
503 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000504}
505
George Rimar85011022019-09-13 16:00:16 +0000506void WasmWriter::writeSectionContent(raw_ostream &OS,
507 WasmYAML::DataCountSection &Section) {
Thomas Livelyfef8de62019-04-12 22:27:48 +0000508 encodeULEB128(Section.Count, OS);
Thomas Livelyfef8de62019-04-12 22:27:48 +0000509}
510
George Rimar85011022019-09-13 16:00:16 +0000511void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
Sam Clegg6f08c842018-04-24 18:11:36 +0000512 uint32_t SectionIndex) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000513 switch (Sec.Type) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000514 case wasm::WASM_SEC_CODE:
515 writeStringRef("reloc.CODE", OS);
516 break;
517 case wasm::WASM_SEC_DATA:
518 writeStringRef("reloc.DATA", OS);
519 break;
520 case wasm::WASM_SEC_CUSTOM: {
521 auto CustomSection = dyn_cast<WasmYAML::CustomSection>(&Sec);
Heejin Ahnf208f632018-09-05 01:27:38 +0000522 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
523 break;
524 }
525 default:
526 llvm_unreachable("not yet implemented");
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000527 }
528
Sam Clegg6f08c842018-04-24 18:11:36 +0000529 encodeULEB128(SectionIndex, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000530 encodeULEB128(Sec.Relocations.size(), OS);
531
Heejin Ahnf208f632018-09-05 01:27:38 +0000532 for (auto Reloc : Sec.Relocations) {
Sam Clegg03e101f2018-03-01 18:06:21 +0000533 writeUint8(OS, Reloc.Type);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000534 encodeULEB128(Reloc.Offset, OS);
535 encodeULEB128(Reloc.Index, OS);
536 switch (Reloc.Type) {
Sam Cleggd1152a22019-02-04 17:28:46 +0000537 case wasm::R_WASM_MEMORY_ADDR_LEB:
538 case wasm::R_WASM_MEMORY_ADDR_SLEB:
539 case wasm::R_WASM_MEMORY_ADDR_I32:
540 case wasm::R_WASM_FUNCTION_OFFSET_I32:
541 case wasm::R_WASM_SECTION_OFFSET_I32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000542 encodeULEB128(Reloc.Addend, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000543 }
544 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000545}
546
George Rimar7da559f2019-09-13 09:12:38 +0000547bool WasmWriter::writeWasm(raw_ostream &OS) {
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000548 // Write headers
549 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
550 writeUint32(OS, Obj.Header.Version);
551
552 // Write each section
Heejin Ahnfeef7202018-12-15 00:58:12 +0000553 llvm::object::WasmSectionOrderChecker Checker;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000554 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Heejin Ahnfeef7202018-12-15 00:58:12 +0000555 StringRef SecName = "";
556 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
557 SecName = S->Name;
558 if (!Checker.isValidSectionOrder(Sec->Type, SecName)) {
George Rimar85011022019-09-13 16:00:16 +0000559 reportError("out of order section type: " + Twine(Sec->Type));
George Rimar7da559f2019-09-13 09:12:38 +0000560 return false;
Heejin Ahnfeef7202018-12-15 00:58:12 +0000561 }
Sam Clegge53af7f2018-01-09 21:38:53 +0000562 encodeULEB128(Sec->Type, OS);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000563 std::string OutString;
564 raw_string_ostream StringStream(OutString);
George Rimar85011022019-09-13 16:00:16 +0000565 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get()))
566 writeSectionContent(StringStream, *S);
567 else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get()))
568 writeSectionContent(StringStream, *S);
569 else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get()))
570 writeSectionContent(StringStream, *S);
571 else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get()))
572 writeSectionContent(StringStream, *S);
573 else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get()))
574 writeSectionContent(StringStream, *S);
575 else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get()))
576 writeSectionContent(StringStream, *S);
577 else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get()))
578 writeSectionContent(StringStream, *S);
579 else if (auto S = dyn_cast<WasmYAML::EventSection>(Sec.get()))
580 writeSectionContent(StringStream, *S);
581 else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get()))
582 writeSectionContent(StringStream, *S);
583 else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get()))
584 writeSectionContent(StringStream, *S);
585 else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get()))
586 writeSectionContent(StringStream, *S);
587 else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get()))
588 writeSectionContent(StringStream, *S);
589 else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get()))
590 writeSectionContent(StringStream, *S);
591 else if (auto S = dyn_cast<WasmYAML::DataCountSection>(Sec.get()))
592 writeSectionContent(StringStream, *S);
593 else
594 reportError("unknown section type: " + Twine(Sec->Type));
595
596 if (HasError)
George Rimar7da559f2019-09-13 09:12:38 +0000597 return false;
George Rimar85011022019-09-13 16:00:16 +0000598
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000599 StringStream.flush();
600
601 // Write the section size followed by the content
602 encodeULEB128(OutString.size(), OS);
603 OS << OutString;
604 }
605
606 // write reloc sections for any section that have relocations
Sam Clegg6f08c842018-04-24 18:11:36 +0000607 uint32_t SectionIndex = 0;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000608 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
Sam Clegg6f08c842018-04-24 18:11:36 +0000609 if (Sec->Relocations.empty()) {
610 SectionIndex++;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000611 continue;
Sam Clegg6f08c842018-04-24 18:11:36 +0000612 }
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000613
Sam Clegg03e101f2018-03-01 18:06:21 +0000614 writeUint8(OS, wasm::WASM_SEC_CUSTOM);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000615 std::string OutString;
616 raw_string_ostream StringStream(OutString);
Sam Clegg6f08c842018-04-24 18:11:36 +0000617 writeRelocSection(StringStream, *Sec, SectionIndex++);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000618 StringStream.flush();
619
620 encodeULEB128(OutString.size(), OS);
621 OS << OutString;
622 }
623
George Rimar7da559f2019-09-13 09:12:38 +0000624 return true;
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000625}
626
Alex Brachetc22d9662019-08-07 02:44:49 +0000627namespace llvm {
628namespace yaml {
629
George Rimar85011022019-09-13 16:00:16 +0000630bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH) {
631 WasmWriter Writer(Doc, EH);
Derek Schuffd3d84fd2017-03-30 19:44:09 +0000632 return Writer.writeWasm(Out);
633}
Alex Brachetc22d9662019-08-07 02:44:49 +0000634
635} // namespace yaml
636} // namespace llvm