LLVM: lib/ObjectYAML/WasmEmitter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
20
21using namespace llvm;
22
23namespace {
24
25
26class WasmWriter {
27public:
29 : Obj(Obj), ErrHandler(EH) {}
30 bool writeWasm(raw_ostream &OS);
31
32private:
33 void writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
34 uint32_t SectionIndex);
35
36 void writeInitExpr(raw_ostream &OS, const WasmYAML::InitExpr &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::TagSection &Section);
45 void writeSectionContent(raw_ostream &OS, WasmYAML::GlobalSection &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);
52
53
54 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,
59 WasmYAML::TargetFeaturesSection &Section);
60 WasmYAML::Object &Obj;
61 uint32_t NumImportedFunctions = 0;
62 uint32_t NumImportedGlobals = 0;
63 uint32_t NumImportedTables = 0;
64 uint32_t NumImportedTags = 0;
65
66 bool HasError = false;
69};
70
71class SubSectionWriter {
72 raw_ostream &OS;
73 std::string OutString;
74 raw_string_ostream StringStream;
75
76public:
77 SubSectionWriter(raw_ostream &OS) : OS(OS), StringStream(OutString) {}
78
79 void done() {
80 StringStream.flush();
82 OS << OutString;
83 OutString.clear();
84 }
85
86 raw_ostream &getStream() { return StringStream; }
87};
88
89}
90
97
104
111
114 OS << Str;
115 return 0;
116}
117
125
126void WasmWriter::reportError(const Twine &Msg) {
127 ErrHandler(Msg);
128 HasError = true;
129}
130
131void WasmWriter::writeInitExpr(raw_ostream &OS,
132 const WasmYAML::InitExpr &InitExpr) {
135 } else {
140 break;
143 break;
146 break;
149 break;
152 break;
153 default:
154 reportError("unknown opcode in init_expr: " +
156 return;
157 }
159 }
160}
161
162void WasmWriter::writeSectionContent(raw_ostream &OS,
163 WasmYAML::DylinkSection &Section) {
165
167 SubSectionWriter SubSection(OS);
168 raw_ostream &SubOS = SubSection.getStream();
173 SubSection.done();
174
175 if (Section.Needed.size()) {
177 raw_ostream &SubOS = SubSection.getStream();
179 for (StringRef Needed : Section.Needed)
181 SubSection.done();
182 }
183 if (Section.RuntimePath.size()) {
185 raw_ostream &SubOS = SubSection.getStream();
187 for (StringRef Path : Section.RuntimePath)
189 SubSection.done();
190 }
191}
192
193void WasmWriter::writeSectionContent(raw_ostream &OS,
194 WasmYAML::LinkingSection &Section) {
197
198 SubSectionWriter SubSection(OS);
199
200
201 if (Section.SymbolTable.size()) {
205 const WasmYAML::SymbolInfo &Info = Sym.value();
209 switch (Info.Kind) {
218 break;
225 }
226 break;
229 break;
230 default:
232 }
233 }
234
235 SubSection.done();
236 }
237
238
239 if (Section.SegmentInfos.size()) {
242 for (const WasmYAML::SegmentInfo &SegmentInfo : Section.SegmentInfos) {
246 }
247 SubSection.done();
248 }
249
250
251 if (Section.InitFunctions.size()) {
254 for (const WasmYAML::InitFunction &Func : Section.InitFunctions) {
257 }
258 SubSection.done();
259 }
260
261
262 if (Section.Comdats.size()) {
265 for (const auto &C : Section.Comdats) {
267 encodeULEB128(0, SubSection.getStream());
268 encodeULEB128(C.Entries.size(), SubSection.getStream());
269 for (const WasmYAML::ComdatEntry &Entry : C.Entries) {
272 }
273 }
274 SubSection.done();
275 }
276}
277
278void WasmWriter::writeSectionContent(raw_ostream &OS,
279 WasmYAML::NameSection &Section) {
281 if (Section.FunctionNames.size()) {
283
284 SubSectionWriter SubSection(OS);
285
287 for (const WasmYAML::NameEntry &NameEntry : Section.FunctionNames) {
290 }
291
292 SubSection.done();
293 }
294 if (Section.GlobalNames.size()) {
296
297 SubSectionWriter SubSection(OS);
298
300 for (const WasmYAML::NameEntry &NameEntry : Section.GlobalNames) {
303 }
304
305 SubSection.done();
306 }
307 if (Section.DataSegmentNames.size()) {
309
310 SubSectionWriter SubSection(OS);
311
313 for (const WasmYAML::NameEntry &NameEntry : Section.DataSegmentNames) {
316 }
317
318 SubSection.done();
319 }
320}
321
322void WasmWriter::writeSectionContent(raw_ostream &OS,
323 WasmYAML::ProducersSection &Section) {
325 int Fields = int(.Languages.empty()) + int(
.Tools.empty()) +
326 int(.SDKs.empty());
327 if (Fields == 0)
328 return;
330 for (auto &Field : {std::make_pair(StringRef("language"), &Section.Languages),
331 std::make_pair(StringRef("processed-by"), &Section.Tools),
332 std::make_pair(StringRef("sdk"), &Section.SDKs)}) {
333 if (Field.second->empty())
334 continue;
337 for (auto &Entry : *Field.second) {
340 }
341 }
342}
343
344void WasmWriter::writeSectionContent(raw_ostream &OS,
345 WasmYAML::TargetFeaturesSection &Section) {
348 for (auto &E : Section.Features) {
351 }
352}
353
354void WasmWriter::writeSectionContent(raw_ostream &OS,
355 WasmYAML::CustomSection &Section) {
357 writeSectionContent(OS, *S);
359 writeSectionContent(OS, *S);
361 writeSectionContent(OS, *S);
363 writeSectionContent(OS, *S);
365 writeSectionContent(OS, *S);
366 } else {
368 Section.Payload.writeAsBinary(OS);
369 }
370}
371
372void WasmWriter::writeSectionContent(raw_ostream &OS,
373 WasmYAML::TypeSection &Section) {
375 uint32_t ExpectedIndex = 0;
376 for (const WasmYAML::Signature &Sig : Section.Signatures) {
377 if (Sig.Index != ExpectedIndex) {
379 return;
380 }
381 ++ExpectedIndex;
384 for (auto ParamType : Sig.ParamTypes)
389 }
390}
391
392void WasmWriter::writeSectionContent(raw_ostream &OS,
393 WasmYAML::ImportSection &Section) {
395 for (const WasmYAML::Import &Import : Section.Imports) {
399 switch (Import.Kind) {
402 NumImportedFunctions++;
403 break;
407 NumImportedGlobals++;
408 break;
410 writeUint8(OS, 0);
412 NumImportedTags++;
413 break;
416 break;
420 NumImportedTables++;
421 break;
422 default:
424 return;
425 }
426 }
427}
428
429void WasmWriter::writeSectionContent(raw_ostream &OS,
430 WasmYAML::FunctionSection &Section) {
432 for (uint32_t FuncType : Section.FunctionTypes)
434}
435
436void WasmWriter::writeSectionContent(raw_ostream &OS,
437 WasmYAML::ExportSection &Section) {
439 for (const WasmYAML::Export &Export : Section.Exports) {
443 }
444}
445
446void WasmWriter::writeSectionContent(raw_ostream &OS,
447 WasmYAML::StartSection &Section) {
449}
450
451void WasmWriter::writeSectionContent(raw_ostream &OS,
452 WasmYAML::TableSection &Section) {
454 uint32_t ExpectedIndex = NumImportedTables;
455 for (auto &Table : Section.Tables) {
456 if (Table.Index != ExpectedIndex) {
457 reportError("unexpected table index: " + Twine(Table.Index));
458 return;
459 }
460 ++ExpectedIndex;
463 }
464}
465
466void WasmWriter::writeSectionContent(raw_ostream &OS,
467 WasmYAML::MemorySection &Section) {
469 for (const WasmYAML::Limits &Mem : Section.Memories)
471}
472
473void WasmWriter::writeSectionContent(raw_ostream &OS,
474 WasmYAML::TagSection &Section) {
476 for (uint32_t TagType : Section.TagTypes) {
477 writeUint8(OS, 0);
479 }
480}
481
482void WasmWriter::writeSectionContent(raw_ostream &OS,
483 WasmYAML::GlobalSection &Section) {
485 uint32_t ExpectedIndex = NumImportedGlobals;
487 if (Global.Index != ExpectedIndex) {
489 return;
490 }
491 ++ExpectedIndex;
494 writeInitExpr(OS, Global.Init);
495 }
496}
497
498void WasmWriter::writeSectionContent(raw_ostream &OS,
499 WasmYAML::ElemSection &Section) {
501 for (auto &Segment : Section.Segments) {
505
506 writeInitExpr(OS, Segment.Offset);
507
509
510
511
512 if (Segment.ElemKind != uint32_t(wasm::ValType::FUNCREF)) {
513 reportError("unexpected elemkind: " + Twine(Segment.ElemKind));
514 return;
515 }
516 const uint8_t ElemKind = 0;
518 }
519
521 for (auto &Function : Segment.Functions)
523 }
524}
525
526void WasmWriter::writeSectionContent(raw_ostream &OS,
527 WasmYAML::CodeSection &Section) {
529 uint32_t ExpectedIndex = NumImportedFunctions;
530 for (auto &Func : Section.Functions) {
531 std::string OutString;
532 raw_string_ostream StringStream(OutString);
533 if (Func.Index != ExpectedIndex) {
534 reportError("unexpected function index: " + Twine(Func.Index));
535 return;
536 }
537 ++ExpectedIndex;
538
540 for (auto &LocalDecl : Func.Locals) {
542 writeUint8(StringStream, LocalDecl.Type);
543 }
544
545 Func.Body.writeAsBinary(StringStream);
546
547
548 StringStream.flush();
550 OS << OutString;
551 }
552}
553
554void WasmWriter::writeSectionContent(raw_ostream &OS,
555 WasmYAML::DataSection &Section) {
557 for (auto &Segment : Section.Segments) {
562 writeInitExpr(OS, Segment.Offset);
563 encodeULEB128(Segment.Content.binary_size(), OS);
564 Segment.Content.writeAsBinary(OS);
565 }
566}
567
568void WasmWriter::writeSectionContent(raw_ostream &OS,
569 WasmYAML::DataCountSection &Section) {
571}
572
573void WasmWriter::writeRelocSection(raw_ostream &OS, WasmYAML::Section &Sec,
574 uint32_t SectionIndex) {
575 switch (Sec.Type) {
578 break;
581 break;
584 writeStringRef(("reloc." + CustomSection->Name).str(), OS);
585 break;
586 }
587 default:
589 }
590
593
600 }
601}
602
603bool WasmWriter::writeWasm(raw_ostream &OS) {
604
607
608
609 llvm::object::WasmSectionOrderChecker Checker;
610 for (const std::unique_ptrWasmYAML::Section &Sec : Obj.Sections) {
611 StringRef SecName = "";
613 SecName = S->Name;
615 reportError("out of order section type: " +
617 return false;
618 }
620 std::string OutString;
621 raw_string_ostream StringStream(OutString);
623 writeSectionContent(StringStream, *S);
625 writeSectionContent(StringStream, *S);
627 writeSectionContent(StringStream, *S);
629 writeSectionContent(StringStream, *S);
631 writeSectionContent(StringStream, *S);
633 writeSectionContent(StringStream, *S);
635 writeSectionContent(StringStream, *S);
637 writeSectionContent(StringStream, *S);
639 writeSectionContent(StringStream, *S);
641 writeSectionContent(StringStream, *S);
643 writeSectionContent(StringStream, *S);
645 writeSectionContent(StringStream, *S);
647 writeSectionContent(StringStream, *S);
649 writeSectionContent(StringStream, *S);
650 else
651 reportError("unknown section type: " + Twine(Sec->Type));
652
653 if (HasError)
654 return false;
655
656 StringStream.flush();
657
658 unsigned HeaderSecSizeEncodingLen =
659 Sec->HeaderSecSizeEncodingLen.value_or(5);
660 unsigned RequiredLen = getULEB128Size(OutString.size());
661
662 assert(RequiredLen <= 5);
663 if (HeaderSecSizeEncodingLen < RequiredLen) {
664 reportError("section header length can't be encoded in a LEB of size " +
665 Twine(HeaderSecSizeEncodingLen));
666 return false;
667 }
668
669 encodeULEB128(OutString.size(), OS, HeaderSecSizeEncodingLen);
670 OS << OutString;
671 }
672
673
674 uint32_t SectionIndex = 0;
675 for (const std::unique_ptrWasmYAML::Section &Sec : Obj.Sections) {
676 if (Sec->Relocations.empty()) {
677 SectionIndex++;
678 continue;
679 }
680
682 std::string OutString;
683 raw_string_ostream StringStream(OutString);
684 writeRelocSection(StringStream, *Sec, SectionIndex++);
685 StringStream.flush();
686
688 OS << OutString;
689 }
690
691 return true;
692}
693
694namespace llvm {
695namespace yaml {
696
698 WasmWriter Writer(Doc, EH);
699 return Writer.writeWasm(Out);
700}
701
702}
703}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Error reportError(StringRef Message)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
OptimizedStructLayoutField Field
static int writeUint32(raw_ostream &OS, uint32_t Value)
Definition WasmEmitter.cpp:98
static int writeLimits(const WasmYAML::Limits &Lim, raw_ostream &OS)
Definition WasmEmitter.cpp:118
static int writeStringRef(const StringRef &Str, raw_ostream &OS)
Definition WasmEmitter.cpp:112
static int writeUint8(raw_ostream &OS, uint8_t Value)
Definition WasmEmitter.cpp:105
static int writeUint64(raw_ostream &OS, uint64_t Value)
Definition WasmEmitter.cpp:91
StringRef - Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
LLVM_ABI bool isValidSectionOrder(unsigned ID, StringRef CustomSectionName="")
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write(unsigned char C)
LLVM_ABI void writeAsBinary(raw_ostream &OS, uint64_t N=UINT64_MAX) const
Write the contents (regardless of whether it is binary or a hex string) as binary to the given raw_os...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
NodeAddr< FuncNode * > Func
void write64le(void *P, uint64_t V)
void write32le(void *P, uint32_t V)
const unsigned WASM_SYMBOL_UNDEFINED
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
LLVM_ABI bool relocTypeHasAddend(uint32_t type)
@ WASM_DYLINK_RUNTIME_PATH
@ WASM_NAMES_DATA_SEGMENT
LLVM_ABI llvm::StringRef sectionTypeToString(uint32_t type)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
llvm::function_ref< void(const Twine &Msg)> ErrorHandler
LLVM_ABI bool yaml2wasm(WasmYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH)
Definition WasmEmitter.cpp:697
This is an optimization pass for GlobalISel generic memory operations.
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
@ Export
Export information to summary.
@ Import
Import information from summary.
@ Global
Append to llvm.global_dtors.
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
wasm::WasmInitExprMVP Inst
std::vector< std::unique_ptr< Section > > Sections
std::vector< Relocation > Relocations
std::vector< ValueType > ReturnTypes
std::vector< ValueType > ParamTypes
union llvm::wasm::WasmInitExprMVP::@021046217255127373215144224227277301132130072341 Value
Common declarations for yaml2obj.