[X86] Don't report gather is legal on Skylake CPUs when AVX2/AVX512 is disabled....
[llvm-complete.git] / tools / yaml2obj / yaml2wasm.cpp
blobbb8f4ff3b5061ab399e0f3fa6143e7a136de4213
1 //===- yaml2wasm - Convert YAML to a Wasm object file --------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief The Wasm component of yaml2obj.
12 ///
13 //===----------------------------------------------------------------------===//
15 #include "yaml2obj.h"
16 #include "llvm/Object/Wasm.h"
17 #include "llvm/ObjectYAML/ObjectYAML.h"
18 #include "llvm/Support/Endian.h"
19 #include "llvm/Support/LEB128.h"
21 using namespace llvm;
23 /// This parses a yaml stream that represents a Wasm object file.
24 /// See docs/yaml2obj for the yaml scheema.
25 class WasmWriter {
26 public:
27 WasmWriter(WasmYAML::Object &Obj) : Obj(Obj) {}
28 int writeWasm(raw_ostream &OS);
30 private:
31 int writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec);
33 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);
40 int writeSectionContent(raw_ostream &OS, WasmYAML::ExportSection &Section);
41 int writeSectionContent(raw_ostream &OS, WasmYAML::StartSection &Section);
42 int writeSectionContent(raw_ostream &OS, WasmYAML::ElemSection &Section);
43 int writeSectionContent(raw_ostream &OS, WasmYAML::CodeSection &Section);
44 int writeSectionContent(raw_ostream &OS, WasmYAML::DataSection &Section);
46 // Custom section types
47 int writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section);
48 int writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section);
49 WasmYAML::Object &Obj;
52 static int writeUint64(raw_ostream &OS, uint64_t Value) {
53 char Data[sizeof(Value)];
54 support::endian::write64le(Data, Value);
55 OS.write(Data, sizeof(Data));
56 return 0;
59 static int writeUint32(raw_ostream &OS, uint32_t Value) {
60 char Data[sizeof(Value)];
61 support::endian::write32le(Data, Value);
62 OS.write(Data, sizeof(Data));
63 return 0;
66 static int writeUint8(raw_ostream &OS, uint8_t Value) {
67 char Data[sizeof(Value)];
68 memcpy(Data, &Value, sizeof(Data));
69 OS.write(Data, sizeof(Data));
70 return 0;
73 static int writeStringRef(const StringRef &Str, raw_ostream &OS) {
74 encodeULEB128(Str.size(), OS);
75 OS << Str;
76 return 0;
79 static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS) {
80 encodeULEB128(Lim.Flags, OS);
81 encodeULEB128(Lim.Initial, OS);
82 if (Lim.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
83 encodeULEB128(Lim.Maximum, OS);
84 return 0;
87 static int writeInitExpr(const wasm::WasmInitExpr &InitExpr, raw_ostream &OS) {
88 writeUint8(OS, InitExpr.Opcode);
89 switch (InitExpr.Opcode) {
90 case wasm::WASM_OPCODE_I32_CONST:
91 encodeSLEB128(InitExpr.Value.Int32, OS);
92 break;
93 case wasm::WASM_OPCODE_I64_CONST:
94 encodeSLEB128(InitExpr.Value.Int64, OS);
95 break;
96 case wasm::WASM_OPCODE_F32_CONST:
97 writeUint32(OS, InitExpr.Value.Float32);
98 break;
99 case wasm::WASM_OPCODE_F64_CONST:
100 writeUint64(OS, InitExpr.Value.Float64);
101 break;
102 case wasm::WASM_OPCODE_GET_GLOBAL:
103 encodeULEB128(InitExpr.Value.Global, OS);
104 break;
105 default:
106 errs() << "Unknown opcode in init_expr: " << InitExpr.Opcode;
107 return 1;
109 writeUint8(OS, wasm::WASM_OPCODE_END);
110 return 0;
113 class SubSectionWriter {
114 raw_ostream &OS;
115 std::string OutString;
116 raw_string_ostream StringStream;
118 public:
119 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
121 void Done() {
122 StringStream.flush();
123 encodeULEB128(OutString.size(), OS);
124 OS << OutString;
125 OutString.clear();
128 raw_ostream& GetStream() {
129 return StringStream;
133 int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::LinkingSection &Section) {
134 writeStringRef(Section.Name, OS);
136 SubSectionWriter SubSection(OS);
138 // DATA_SIZE subsection
139 encodeULEB128(wasm::WASM_DATA_SIZE, OS);
140 encodeULEB128(Section.DataSize, SubSection.GetStream());
141 SubSection.Done();
143 // SYMBOL_INFO subsection
144 if (Section.SymbolInfos.size()) {
145 encodeULEB128(wasm::WASM_SYMBOL_INFO, OS);
147 encodeULEB128(Section.SymbolInfos.size(), SubSection.GetStream());
148 for (const WasmYAML::SymbolInfo &Info : Section.SymbolInfos) {
149 writeStringRef(Info.Name, SubSection.GetStream());
150 encodeULEB128(Info.Flags, SubSection.GetStream());
153 SubSection.Done();
156 // SEGMENT_NAMES subsection
157 if (Section.SegmentInfos.size()) {
158 encodeULEB128(wasm::WASM_SEGMENT_INFO, OS);
159 encodeULEB128(Section.SegmentInfos.size(), SubSection.GetStream());
160 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
161 encodeULEB128(SegmentInfo.Index, SubSection.GetStream());
162 writeStringRef(SegmentInfo.Name, SubSection.GetStream());
163 encodeULEB128(SegmentInfo.Alignment, SubSection.GetStream());
164 encodeULEB128(SegmentInfo.Flags, SubSection.GetStream());
166 SubSection.Done();
168 return 0;
171 int WasmWriter::writeSectionContent(raw_ostream &OS, WasmYAML::NameSection &Section) {
172 writeStringRef(Section.Name, OS);
173 if (Section.FunctionNames.size()) {
174 encodeULEB128(wasm::WASM_NAMES_FUNCTION, OS);
176 SubSectionWriter SubSection(OS);
178 encodeULEB128(Section.FunctionNames.size(), SubSection.GetStream());
179 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
180 encodeULEB128(NameEntry.Index, SubSection.GetStream());
181 writeStringRef(NameEntry.Name, SubSection.GetStream());
184 SubSection.Done();
186 return 0;
189 int WasmWriter::writeSectionContent(raw_ostream &OS,
190 WasmYAML::CustomSection &Section) {
191 if (auto S = dyn_cast<WasmYAML::NameSection>(&Section)) {
192 if (auto Err = writeSectionContent(OS, *S))
193 return Err;
194 } else if (auto S = dyn_cast<WasmYAML::LinkingSection>(&Section)) {
195 if (auto Err = writeSectionContent(OS, *S))
196 return Err;
197 } else {
198 Section.Payload.writeAsBinary(OS);
200 return 0;
203 int WasmWriter::writeSectionContent(raw_ostream &OS,
204 WasmYAML::TypeSection &Section) {
205 encodeULEB128(Section.Signatures.size(), OS);
206 for (const WasmYAML::Signature &Sig : Section.Signatures) {
207 encodeSLEB128(Sig.Form, OS);
208 encodeULEB128(Sig.ParamTypes.size(), OS);
209 for (auto ParamType : Sig.ParamTypes)
210 encodeSLEB128(ParamType, OS);
211 if (Sig.ReturnType == wasm::WASM_TYPE_NORESULT) {
212 encodeSLEB128(0, OS);
213 } else {
214 encodeULEB128(1, OS);
215 encodeSLEB128(Sig.ReturnType, OS);
218 return 0;
221 int WasmWriter::writeSectionContent(raw_ostream &OS,
222 WasmYAML::ImportSection &Section) {
223 encodeULEB128(Section.Imports.size(), OS);
224 for (const WasmYAML::Import &Import : Section.Imports) {
225 writeStringRef(Import.Module, OS);
226 writeStringRef(Import.Field, OS);
227 encodeULEB128(Import.Kind, OS);
228 switch (Import.Kind) {
229 case wasm::WASM_EXTERNAL_FUNCTION:
230 encodeULEB128(Import.SigIndex, OS);
231 break;
232 case wasm::WASM_EXTERNAL_GLOBAL:
233 encodeSLEB128(Import.GlobalImport.Type, OS);
234 writeUint8(OS, Import.GlobalImport.Mutable);
235 break;
236 case wasm::WASM_EXTERNAL_MEMORY:
237 writeLimits(Import.Memory, OS);
238 break;
239 case wasm::WASM_EXTERNAL_TABLE:
240 encodeSLEB128(Import.TableImport.ElemType, OS);
241 writeLimits(Import.TableImport.TableLimits, OS);
242 break;
243 default:
244 errs() << "Unknown import type: " << Import.Kind;
245 return 1;
248 return 0;
251 int WasmWriter::writeSectionContent(raw_ostream &OS,
252 WasmYAML::FunctionSection &Section) {
253 encodeULEB128(Section.FunctionTypes.size(), OS);
254 for (uint32_t FuncType : Section.FunctionTypes) {
255 encodeULEB128(FuncType, OS);
257 return 0;
260 int WasmWriter::writeSectionContent(raw_ostream &OS,
261 WasmYAML::ExportSection &Section) {
262 encodeULEB128(Section.Exports.size(), OS);
263 for (const WasmYAML::Export &Export : Section.Exports) {
264 writeStringRef(Export.Name, OS);
265 encodeULEB128(Export.Kind, OS);
266 encodeULEB128(Export.Index, OS);
268 return 0;
271 int WasmWriter::writeSectionContent(raw_ostream &OS,
272 WasmYAML::StartSection &Section) {
273 encodeULEB128(Section.StartFunction, OS);
274 return 0;
277 int WasmWriter::writeSectionContent(raw_ostream &OS,
278 WasmYAML::TableSection &Section) {
279 encodeULEB128(Section.Tables.size(), OS);
280 for (auto &Table : Section.Tables) {
281 encodeSLEB128(Table.ElemType, OS);
282 writeLimits(Table.TableLimits, OS);
284 return 0;
287 int WasmWriter::writeSectionContent(raw_ostream &OS,
288 WasmYAML::MemorySection &Section) {
289 encodeULEB128(Section.Memories.size(), OS);
290 for (const WasmYAML::Limits &Mem : Section.Memories) {
291 writeLimits(Mem, OS);
293 return 0;
296 int WasmWriter::writeSectionContent(raw_ostream &OS,
297 WasmYAML::GlobalSection &Section) {
298 encodeULEB128(Section.Globals.size(), OS);
299 for (auto &Global : Section.Globals) {
300 encodeSLEB128(Global.Type, OS);
301 writeUint8(OS, Global.Mutable);
302 writeInitExpr(Global.InitExpr, OS);
304 return 0;
307 int WasmWriter::writeSectionContent(raw_ostream &OS,
308 WasmYAML::ElemSection &Section) {
309 encodeULEB128(Section.Segments.size(), OS);
310 for (auto &Segment : Section.Segments) {
311 encodeULEB128(Segment.TableIndex, OS);
312 writeInitExpr(Segment.Offset, OS);
314 encodeULEB128(Segment.Functions.size(), OS);
315 for (auto &Function : Segment.Functions) {
316 encodeULEB128(Function, OS);
319 return 0;
322 int WasmWriter::writeSectionContent(raw_ostream &OS,
323 WasmYAML::CodeSection &Section) {
324 encodeULEB128(Section.Functions.size(), OS);
325 for (auto &Func : Section.Functions) {
326 std::string OutString;
327 raw_string_ostream StringStream(OutString);
329 encodeULEB128(Func.Locals.size(), StringStream);
330 for (auto &LocalDecl : Func.Locals) {
331 encodeULEB128(LocalDecl.Count, StringStream);
332 encodeSLEB128(LocalDecl.Type, StringStream);
335 Func.Body.writeAsBinary(StringStream);
337 // Write the section size followed by the content
338 StringStream.flush();
339 encodeULEB128(OutString.size(), OS);
340 OS << OutString;
342 return 0;
345 int WasmWriter::writeSectionContent(raw_ostream &OS,
346 WasmYAML::DataSection &Section) {
347 encodeULEB128(Section.Segments.size(), OS);
348 for (auto &Segment : Section.Segments) {
349 encodeULEB128(Segment.MemoryIndex, OS);
350 writeInitExpr(Segment.Offset, OS);
351 encodeULEB128(Segment.Content.binary_size(), OS);
352 Segment.Content.writeAsBinary(OS);
354 return 0;
357 int WasmWriter::writeRelocSection(raw_ostream &OS,
358 WasmYAML::Section &Sec) {
359 StringRef Name;
360 switch (Sec.Type) {
361 case wasm::WASM_SEC_CODE:
362 Name = "reloc.CODE";
363 break;
364 case wasm::WASM_SEC_DATA:
365 Name = "reloc.DATA";
366 break;
367 default:
368 llvm_unreachable("not yet implemented");
369 return 1;
372 writeStringRef(Name, OS);
373 encodeULEB128(Sec.Type, OS);
374 encodeULEB128(Sec.Relocations.size(), OS);
376 for (auto Reloc: Sec.Relocations) {
377 encodeULEB128(Reloc.Type, OS);
378 encodeULEB128(Reloc.Offset, OS);
379 encodeULEB128(Reloc.Index, OS);
380 switch (Reloc.Type) {
381 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
382 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
383 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
384 encodeULEB128(Reloc.Addend, OS);
387 return 0;
391 int WasmWriter::writeWasm(raw_ostream &OS) {
392 // Write headers
393 OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
394 writeUint32(OS, Obj.Header.Version);
396 // Write each section
397 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
398 encodeULEB128(Sec->Type, OS);
400 std::string OutString;
401 raw_string_ostream StringStream(OutString);
402 if (auto S = dyn_cast<WasmYAML::CustomSection>(Sec.get())) {
403 if (auto Err = writeSectionContent(StringStream, *S))
404 return Err;
405 } else if (auto S = dyn_cast<WasmYAML::TypeSection>(Sec.get())) {
406 if (auto Err = writeSectionContent(StringStream, *S))
407 return Err;
408 } else if (auto S = dyn_cast<WasmYAML::ImportSection>(Sec.get())) {
409 if (auto Err = writeSectionContent(StringStream, *S))
410 return Err;
411 } else if (auto S = dyn_cast<WasmYAML::FunctionSection>(Sec.get())) {
412 if (auto Err = writeSectionContent(StringStream, *S))
413 return Err;
414 } else if (auto S = dyn_cast<WasmYAML::TableSection>(Sec.get())) {
415 if (auto Err = writeSectionContent(StringStream, *S))
416 return Err;
417 } else if (auto S = dyn_cast<WasmYAML::MemorySection>(Sec.get())) {
418 if (auto Err = writeSectionContent(StringStream, *S))
419 return Err;
420 } else if (auto S = dyn_cast<WasmYAML::GlobalSection>(Sec.get())) {
421 if (auto Err = writeSectionContent(StringStream, *S))
422 return Err;
423 } else if (auto S = dyn_cast<WasmYAML::ExportSection>(Sec.get())) {
424 if (auto Err = writeSectionContent(StringStream, *S))
425 return Err;
426 } else if (auto S = dyn_cast<WasmYAML::StartSection>(Sec.get())) {
427 if (auto Err = writeSectionContent(StringStream, *S))
428 return Err;
429 } else if (auto S = dyn_cast<WasmYAML::ElemSection>(Sec.get())) {
430 if (auto Err = writeSectionContent(StringStream, *S))
431 return Err;
432 } else if (auto S = dyn_cast<WasmYAML::CodeSection>(Sec.get())) {
433 if (auto Err = writeSectionContent(StringStream, *S))
434 return Err;
435 } else if (auto S = dyn_cast<WasmYAML::DataSection>(Sec.get())) {
436 if (auto Err = writeSectionContent(StringStream, *S))
437 return Err;
438 } else {
439 errs() << "Unknown section type: " << Sec->Type << "\n";
440 return 1;
442 StringStream.flush();
444 // Write the section size followed by the content
445 encodeULEB128(OutString.size(), OS);
446 OS << OutString;
449 // write reloc sections for any section that have relocations
450 for (const std::unique_ptr<WasmYAML::Section> &Sec : Obj.Sections) {
451 if (Sec->Relocations.empty())
452 continue;
454 encodeULEB128(wasm::WASM_SEC_CUSTOM, OS);
455 std::string OutString;
456 raw_string_ostream StringStream(OutString);
457 writeRelocSection(StringStream, *Sec);
458 StringStream.flush();
460 encodeULEB128(OutString.size(), OS);
461 OS << OutString;
464 return 0;
467 int yaml2wasm(llvm::WasmYAML::Object &Doc, raw_ostream &Out) {
468 WasmWriter Writer(Doc);
470 return Writer.writeWasm(Out);