LLVM: lib/MC/WasmObjectWriter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
16#include "llvm/Config/llvm-config.h"
31#include
32
33using namespace llvm;
34
35#define DEBUG_TYPE "mc"
36
37namespace {
38
39
40
41static const uint32_t InitialTableOffset = 1;
42
43
44
45
46struct SectionBookkeeping {
47
49
51
54};
55
56
57
58
59
60struct WasmDataSegment {
68};
69
70
71struct WasmFunction {
74};
75
76
77struct WasmGlobal {
80};
81
82
83
84
85struct WasmComdatEntry {
86 unsigned Kind;
88};
89
90
91struct WasmRelocationEntry {
93 const MCSymbolWasm *Symbol;
94 int64_t Addend;
95 unsigned Type;
96 const MCSectionWasm *FixupSection;
97
99 int64_t Addend, unsigned Type,
102 FixupSection(FixupSection) {}
103
105
108 << ", Sym=" << *Symbol << ", Addend=" << Addend
109 << ", FixupSection=" << FixupSection->getName();
110 }
111
112#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
114#endif
115};
116
118
119struct WasmCustomSection {
120
123
124 uint32_t OutputContentsOffset = 0;
126
128 : Name(Name), Section(Section) {}
129};
130
131#if !defined(NDEBUG)
133 Rel.print(OS);
134 return OS;
135}
136#endif
137
138
139
140template <typename T, int W>
144 assert(SizeLen == W);
145 Stream.pwrite((char *)Buffer, SizeLen, Offset);
146}
147
148
149
150template <typename T, int W>
154 assert(SizeLen == W);
155 Stream.pwrite((char *)Buffer, SizeLen, Offset);
156}
157
160 writePatchableULEB<uint32_t, 5>(Stream, Value, Offset);
161}
162
165 writePatchableSLEB<int32_t, 5>(Stream, Value, Offset);
166}
167
170 writePatchableSLEB<uint64_t, 10>(Stream, Value, Offset);
171}
172
175 writePatchableSLEB<int64_t, 10>(Stream, Value, Offset);
176}
177
178
183 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
184}
185
190 Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
191}
192
195}
196
199
200
201 std::unique_ptr TargetObjectWriter;
202
203
204 std::vector CodeRelocations;
205
206 std::vector DataRelocations;
207
208
209
211
212
214
215
218
220
221
222
223 std::vector CustomSections;
224 std::unique_ptr ProducersSection;
225 std::unique_ptr TargetFeaturesSection;
226
228 CustomSectionsRelocations;
229
230
232
236 unsigned NumFunctionImports = 0;
237 unsigned NumGlobalImports = 0;
238 unsigned NumTableImports = 0;
239 unsigned NumTagImports = 0;
241
242 enum class DwoMode {
243 AllSections,
244 NonDwoOnly,
245 DwoOnly,
246 };
247 bool IsSplitDwarf = false;
250
251
252 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
253 bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); }
254
255 void startSection(SectionBookkeeping &Section, unsigned SectionId);
256 void startCustomSection(SectionBookkeeping &Section, StringRef Name);
257 void endSection(SectionBookkeeping &Section);
258
259public:
260 WasmObjectWriter(std::unique_ptr MOTW,
262 : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {}
263
264 WasmObjectWriter(std::unique_ptr MOTW,
266 : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_),
267 DwoOS(&DwoOS_) {}
268
269private:
270 void reset() override {
271 CodeRelocations.clear();
272 DataRelocations.clear();
273 TypeIndices.clear();
274 WasmIndices.clear();
275 GOTIndices.clear();
276 TableIndices.clear();
277 DataLocations.clear();
278 CustomSections.clear();
279 ProducersSection.reset();
280 TargetFeaturesSection.reset();
281 CustomSectionsRelocations.clear();
282 SignatureIndices.clear();
283 Signatures.clear();
284 DataSegments.clear();
285 SectionFunctions.clear();
286 NumFunctionImports = 0;
287 NumGlobalImports = 0;
288 NumTableImports = 0;
290 }
291
292 void writeHeader(const MCAssembler &Asm);
293
296
297 void executePostLayoutBinding() override;
300 uint64_t writeObject() override;
301
303
304 void writeString(const StringRef Str) {
306 W->OS << Str;
307 }
308
309 void writeStringWithAlignment(const StringRef Str, unsigned Alignment);
310
311 void writeI32(int32_t val) {
312 char Buffer[4];
314 W->OS.write(Buffer, sizeof(Buffer));
315 }
316
317 void writeI64(int64_t val) {
318 char Buffer[8];
320 W->OS.write(Buffer, sizeof(Buffer));
321 }
322
323 void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); }
324
330 void writeElemSection(const MCSymbolWasm *IndirectFunctionTable,
332 void writeDataCountSection();
340 std::vector &Relocations);
341 void writeLinkingMetaDataSection(
343 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
344 const std::map<StringRef, std::vector> &Comdats);
345 void writeCustomSection(WasmCustomSection &CustomSection,
347 void writeCustomRelocSections();
348
350 const WasmRelocationEntry &RelEntry);
353
354 uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
357 void registerFunctionType(const MCSymbolWasm &Symbol);
358 void registerTagType(const MCSymbolWasm &Symbol);
359};
360
361}
362
363
364void WasmObjectWriter::startSection(SectionBookkeeping &Section,
365 unsigned SectionId) {
366 LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
367 W->OS << char(SectionId);
368
370
371
372
374
375
378 Section.Index = SectionCount++;
379}
380
381
382
383void WasmObjectWriter::writeStringWithAlignment(const StringRef Str,
384 unsigned Alignment) {
385
386
387
388 raw_null_ostream NullOS;
389 uint64_t StrSizeLength = encodeULEB128(Str.size(), NullOS);
390 uint64_t Offset = W->OS.tell() + StrSizeLength + Str.size();
393
394
395 assert((StrSizeLength + Paddings) <= 5 && "too long string to align");
396
397 encodeSLEB128(Str.size(), W->OS, StrSizeLength + Paddings);
398 W->OS << Str;
399
401}
402
403void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
404 StringRef Name) {
405 LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");
407
408
410
411
412 if (Name != "__clangast") {
413 writeString(Name);
414 } else {
415
416 writeStringWithAlignment(Name, 4);
417 }
418
419
421}
422
423
424
425void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
427
428
430 return;
431
435
437
438
439
440 writePatchableU32(static_cast<raw_pwrite_stream &>(W->OS), Size,
442}
443
444
445void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
448}
449
450void WasmObjectWriter::executePostLayoutBinding() {
451
452
453
454
455
456
457 if (auto *Sym = Asm->getContext().lookupSymbol("__indirect_function_table")) {
458 const auto *WasmSym = static_cast<const MCSymbolWasm *>(Sym);
459 if (WasmSym->isNoStrip())
460 Asm->registerSymbol(*Sym);
461 }
462
463
464
465 for (const MCSymbol &S : Asm->symbols()) {
466 const auto &WS = static_cast<const MCSymbolWasm &>(S);
467 if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
468 const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());
469 auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
470 if (!Pair.second)
472 Sec.getName());
473 }
474 }
475}
476
477void WasmObjectWriter::recordRelocation(const MCFragment &F,
478 const MCFixup &Fixup, MCValue Target,
479 uint64_t &FixedValue) {
480
482
483 const auto &FixupSection = static_cast<MCSectionWasm &>(*F.getParent());
484 uint64_t C = Target.getConstant();
485 uint64_t FixupOffset = Asm->getFragmentOffset(F) + Fixup.getOffset();
487 bool IsLocRel = false;
488
489 if (const auto *RefB = Target.getSubSym()) {
490 auto &SymB = static_cast<const MCSymbolWasm &>(*RefB);
491
492 if (FixupSection.isText()) {
494 Twine("symbol '") + SymB.getName() +
495 "' unsupported subtraction expression used in "
496 "relocation in code section.");
497 return;
498 }
499
500 if (SymB.isUndefined()) {
502 Twine("symbol '") + SymB.getName() +
503 "' can not be undefined in a subtraction expression");
504 return;
505 }
506 const MCSection &SecB = SymB.getSection();
507 if (&SecB != &FixupSection) {
509 Twine("symbol '") + SymB.getName() +
510 "' can not be placed in a different section");
511 return;
512 }
513 IsLocRel = true;
514 C += FixupOffset - Asm->getSymbolOffset(SymB);
515 }
516
517
518 auto *SymA = static_cast<const MCSymbolWasm *>(Target.getAddSym());
519
520
521 if (FixupSection.getName().starts_with(".init_array")) {
522 SymA->setUsedInInitArray();
523 return;
524 }
525
526
527
528
529 FixedValue = 0;
530
531 unsigned Type;
534 else
536 TargetObjectWriter->getRelocType(Target, Fixup, FixupSection, IsLocRel);
537
538
539
540
541 if ((Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
542 Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
543 Type == wasm::R_WASM_SECTION_OFFSET_I32) &&
544 SymA->isDefined()) {
545
546
547
548
549
550 if (!FixupSection.isMetadata())
551 report_fatal_error("relocations for function or section offsets are "
552 "only supported in metadata sections");
553
554 const MCSymbol *SectionSymbol = nullptr;
555 const MCSection &SecA = SymA->getSection();
557 auto SecSymIt = SectionFunctions.find(&SecA);
558 if (SecSymIt == SectionFunctions.end())
560 SectionSymbol = SecSymIt->second;
561 } else {
563 }
564 if (!SectionSymbol)
566
567 C += Asm->getSymbolOffset(*SymA);
568 SymA = static_cast<const MCSymbolWasm *>(SectionSymbol);
569 }
570
571 if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
572 Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 ||
573 Type == wasm::R_WASM_TABLE_INDEX_SLEB ||
574 Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||
575 Type == wasm::R_WASM_TABLE_INDEX_I32 ||
576 Type == wasm::R_WASM_TABLE_INDEX_I64) {
577
578
579 auto TableName = "__indirect_function_table";
580 auto *Sym = static_cast<MCSymbolWasm *>(Ctx.lookupSymbol(TableName));
581 if (!Sym) {
583 } else {
584 if (!Sym->isFunctionTable())
585 report_fatal_error("__indirect_function_table symbol has wrong type");
586
587 Sym->setNoStrip();
588 Asm->registerSymbol(*Sym);
589 }
590 }
591
592
593
594 if (Type != wasm::R_WASM_TYPE_INDEX_LEB) {
595 if (SymA->getName().empty())
596 report_fatal_error("relocations against un-named temporaries are not yet "
597 "supported by wasm");
598
599 SymA->setUsedInReloc();
600 }
601
602 WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
604
605 if (FixupSection.isWasmData()) {
606 DataRelocations.push_back(Rec);
607 } else if (FixupSection.isText()) {
608 CodeRelocations.push_back(Rec);
609 } else if (FixupSection.isMetadata()) {
610 CustomSectionsRelocations[&FixupSection].push_back(Rec);
611 } else {
613 }
614}
615
616
617
618
619
620uint64_t
621WasmObjectWriter::getProvisionalValue(const MCAssembler &Asm,
622 const WasmRelocationEntry &RelEntry) {
623 if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
624 RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
625 !RelEntry.Symbol->isGlobal()) {
626 assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");
627 return GOTIndices[RelEntry.Symbol];
628 }
629
630 switch (RelEntry.Type) {
631 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
632 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
633 case wasm::R_WASM_TABLE_INDEX_SLEB:
634 case wasm::R_WASM_TABLE_INDEX_SLEB64:
635 case wasm::R_WASM_TABLE_INDEX_I32:
636 case wasm::R_WASM_TABLE_INDEX_I64: {
637
639 static_cast<const MCSymbolWasm *>(Asm.getBaseSymbol(*RelEntry.Symbol));
641 if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
642 RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
643 return TableIndices[Base] - InitialTableOffset;
644 else
645 return TableIndices[Base];
646 }
647 case wasm::R_WASM_TYPE_INDEX_LEB:
648
649 return getRelocationIndexValue(RelEntry);
650 case wasm::R_WASM_FUNCTION_INDEX_LEB:
651 case wasm::R_WASM_FUNCTION_INDEX_I32:
652 case wasm::R_WASM_GLOBAL_INDEX_LEB:
653 case wasm::R_WASM_GLOBAL_INDEX_I32:
654 case wasm::R_WASM_TAG_INDEX_LEB:
655 case wasm::R_WASM_TABLE_NUMBER_LEB:
656
657 assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");
658 return WasmIndices[RelEntry.Symbol];
659 case wasm::R_WASM_FUNCTION_OFFSET_I32:
660 case wasm::R_WASM_FUNCTION_OFFSET_I64:
661 case wasm::R_WASM_SECTION_OFFSET_I32: {
662 if (!RelEntry.Symbol->isDefined())
663 return 0;
665 static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
666 return Section.getSectionOffset() + RelEntry.Addend;
667 }
668 case wasm::R_WASM_MEMORY_ADDR_LEB:
669 case wasm::R_WASM_MEMORY_ADDR_LEB64:
670 case wasm::R_WASM_MEMORY_ADDR_SLEB:
671 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
672 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
673 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
674 case wasm::R_WASM_MEMORY_ADDR_I32:
675 case wasm::R_WASM_MEMORY_ADDR_I64:
676 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
677 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
678 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {
679
680
681 if (!RelEntry.Symbol->isDefined())
682 return 0;
683 const wasm::WasmDataReference &SymRef = DataLocations[RelEntry.Symbol];
684 const WasmDataSegment &Segment = DataSegments[SymRef.Segment];
685
686 return Segment.Offset + SymRef.Offset + RelEntry.Addend;
687 }
688 default:
690 }
691}
692
696
698
699 for (const MCFragment &Frag : DataSection) {
700 if (Frag.hasInstructions())
702
705 if (Frag.getAlignFillLen() != 1)
707
708 uint8_t Value = Frag.hasAlignEmitNops() ? 0 : Frag.getAlignFill();
710 std::min<uint64_t>(alignTo(DataBytes.size(), Frag.getAlignment()),
711 DataBytes.size() + Frag.getAlignMaxBytesToEmit());
714 int64_t NumValues;
715 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
716 llvm_unreachable("The fill should be an assembler constant");
717 DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
718 Fill->getValue());
721 } else {
723 }
724 }
725
727}
728
729uint32_t
730WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
731 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
732 auto It = TypeIndices.find(RelEntry.Symbol);
733 if (It == TypeIndices.end())
735 RelEntry.Symbol->getName());
736 return It->second;
737 }
738
739 return RelEntry.Symbol->getIndex();
740}
741
742
743
744void WasmObjectWriter::applyRelocations(
746 const MCAssembler &Asm) {
747 auto &Stream = static_cast<raw_pwrite_stream &>(W->OS);
748 for (const WasmRelocationEntry &RelEntry : Relocations) {
749 uint64_t Offset = ContentsOffset +
751 RelEntry.Offset;
752
753 LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
754 uint64_t Value = getProvisionalValue(Asm, RelEntry);
755
756 switch (RelEntry.Type) {
757 case wasm::R_WASM_FUNCTION_INDEX_LEB:
758 case wasm::R_WASM_TYPE_INDEX_LEB:
759 case wasm::R_WASM_GLOBAL_INDEX_LEB:
760 case wasm::R_WASM_MEMORY_ADDR_LEB:
761 case wasm::R_WASM_TAG_INDEX_LEB:
762 case wasm::R_WASM_TABLE_NUMBER_LEB:
763 writePatchableU32(Stream, Value, Offset);
764 break;
765 case wasm::R_WASM_MEMORY_ADDR_LEB64:
766 writePatchableU64(Stream, Value, Offset);
767 break;
768 case wasm::R_WASM_TABLE_INDEX_I32:
769 case wasm::R_WASM_MEMORY_ADDR_I32:
770 case wasm::R_WASM_FUNCTION_OFFSET_I32:
771 case wasm::R_WASM_FUNCTION_INDEX_I32:
772 case wasm::R_WASM_SECTION_OFFSET_I32:
773 case wasm::R_WASM_GLOBAL_INDEX_I32:
774 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
776 break;
777 case wasm::R_WASM_TABLE_INDEX_I64:
778 case wasm::R_WASM_MEMORY_ADDR_I64:
779 case wasm::R_WASM_FUNCTION_OFFSET_I64:
781 break;
782 case wasm::R_WASM_TABLE_INDEX_SLEB:
783 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
784 case wasm::R_WASM_MEMORY_ADDR_SLEB:
785 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
786 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
787 writePatchableS32(Stream, Value, Offset);
788 break;
789 case wasm::R_WASM_TABLE_INDEX_SLEB64:
790 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
791 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
792 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
793 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
794 writePatchableS64(Stream, Value, Offset);
795 break;
796 default:
798 }
799 }
800}
801
802void WasmObjectWriter::writeTypeSection(
804 if (Signatures.empty())
805 return;
806
807 SectionBookkeeping Section;
809
811
812 for (const wasm::WasmSignature &Sig : Signatures) {
816 writeValueType(Ty);
819 writeValueType(Ty);
820 }
821
822 endSection(Section);
823}
824
827 uint32_t NumElements) {
828 if (Imports.empty())
829 return;
830
831 uint64_t NumPages =
833
834 SectionBookkeeping Section;
836
838 for (const wasm::WasmImport &Import : Imports) {
839 writeString(Import.Module);
840 writeString(Import.Field);
842
843 switch (Import.Kind) {
846 break;
848 W->OS << char(Import.Global.Type);
849 W->OS << char(Import.Global.Mutable ? 1 : 0);
850 break;
854 break;
856 W->OS << char(Import.Table.ElemType);
859 break;
861 W->OS << char(0);
863 break;
864 default:
866 }
867 }
868
869 endSection(Section);
870}
871
873 if (Functions.empty())
874 return;
875
876 SectionBookkeeping Section;
878
880 for (const WasmFunction &Func : Functions)
882
883 endSection(Section);
884}
885
886void WasmObjectWriter::writeTagSection(ArrayRef<uint32_t> TagTypes) {
887 if (TagTypes.empty())
888 return;
889
890 SectionBookkeeping Section;
892
894 for (uint32_t Index : TagTypes) {
895 W->OS << char(0);
897 }
898
899 endSection(Section);
900}
901
903 if (Globals.empty())
904 return;
905
906 SectionBookkeeping Section;
908
910 for (const wasm::WasmGlobal &Global : Globals) {
912 W->OS << char(Global.Type.Mutable);
913 if (Global.InitExpr.Extended) {
915 } else {
916 W->OS << char(Global.InitExpr.Inst.Opcode);
917 switch (Global.Type.Type) {
920 break;
923 break;
925 writeI32(0);
926 break;
928 writeI64(0);
929 break;
931 writeValueType(wasm::ValType::EXTERNREF);
932 break;
933 default:
935 }
936 }
938 }
939
940 endSection(Section);
941}
942
944 if (Tables.empty())
945 return;
946
947 SectionBookkeeping Section;
949
951 for (const wasm::WasmTable &Table : Tables) {
952 assert(Table.Type.ElemType != wasm::ValType::OTHERREF &&
953 "Cannot encode general ref-typed tables");
959 }
960 endSection(Section);
961}
962
964 if (Exports.empty())
965 return;
966
967 SectionBookkeeping Section;
969
971 for (const wasm::WasmExport &Export : Exports) {
972 writeString(Export.Name);
975 }
976
977 endSection(Section);
978}
979
980void WasmObjectWriter::writeElemSection(
981 const MCSymbolWasm *IndirectFunctionTable, ArrayRef<uint32_t> TableElems) {
982 if (TableElems.empty())
983 return;
984
985 assert(IndirectFunctionTable);
986
987 SectionBookkeeping Section;
989
991
992 assert(WasmIndices.count(IndirectFunctionTable));
993 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
994 uint32_t Flags = 0;
995 if (TableNumber)
1000
1001
1006
1008
1009
1010 const uint8_t ElemKind = 0;
1011 W->OS << ElemKind;
1012 }
1013
1015 for (uint32_t Elem : TableElems)
1017
1018 endSection(Section);
1019}
1020
1021void WasmObjectWriter::writeDataCountSection() {
1022 if (DataSegments.empty())
1023 return;
1024
1025 SectionBookkeeping Section;
1028 endSection(Section);
1029}
1030
1031uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
1033 if (Functions.empty())
1034 return 0;
1035
1036 SectionBookkeeping Section;
1038
1040
1041 for (const WasmFunction &Func : Functions) {
1042 auto *FuncSection = static_cast<MCSectionWasm *>(Func.Section);
1043
1044 int64_t Size = Asm.getSectionAddressSize(*FuncSection);
1046 FuncSection->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1047 Asm.writeSectionData(W->OS, FuncSection);
1048 }
1049
1050
1051 applyRelocations(CodeRelocations, Section.ContentsOffset, Asm);
1052
1053 endSection(Section);
1055}
1056
1057uint32_t WasmObjectWriter::writeDataSection(const MCAssembler &Asm) {
1058 if (DataSegments.empty())
1059 return 0;
1060
1061 SectionBookkeeping Section;
1063
1065
1066 for (const WasmDataSegment &Segment : DataSegments) {
1075 }
1077 Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1078 W->OS << Segment.Data;
1079 }
1080
1081
1082 applyRelocations(DataRelocations, Section.ContentsOffset, Asm);
1083
1084 endSection(Section);
1086}
1087
1088void WasmObjectWriter::writeRelocSection(
1089 uint32_t SectionIndex, StringRef Name,
1090 std::vector &Relocs) {
1091
1092
1093
1094 if (Relocs.empty())
1095 return;
1096
1097
1098
1099
1100
1101
1103 Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {
1104 return (A.Offset + A.FixupSection->getSectionOffset()) <
1105 (B.Offset + B.FixupSection->getSectionOffset());
1106 });
1107
1108 SectionBookkeeping Section;
1109 startCustomSection(Section, std::string("reloc.") + Name.str());
1110
1113 for (const WasmRelocationEntry &RelEntry : Relocs) {
1115 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1116 uint32_t Index = getRelocationIndexValue(RelEntry);
1117
1118 W->OS << char(RelEntry.Type);
1121 if (RelEntry.hasAddend())
1123 }
1124
1125 endSection(Section);
1126}
1127
1128void WasmObjectWriter::writeCustomRelocSections() {
1129 for (const auto &Sec : CustomSections) {
1130 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1131 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1132 }
1133}
1134
1135void WasmObjectWriter::writeLinkingMetaDataSection(
1137 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1138 const std::map<StringRef, std::vector> &Comdats) {
1139 SectionBookkeeping Section;
1140 startCustomSection(Section, "linking");
1142
1143 SectionBookkeeping SubSection;
1144 if (SymbolInfos.size() != 0) {
1147 for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
1150 switch (Sym.Kind) {
1158 writeString(Sym.Name);
1159 break;
1161 writeString(Sym.Name);
1166 }
1167 break;
1169 const uint32_t SectionIndex =
1170 CustomSections[Sym.ElementIndex].OutputIndex;
1172 break;
1173 }
1174 default:
1176 }
1177 }
1178 endSection(SubSection);
1179 }
1180
1181 if (DataSegments.size()) {
1184 for (const WasmDataSegment &Segment : DataSegments) {
1185 writeString(Segment.Name);
1188 }
1189 endSection(SubSection);
1190 }
1191
1192 if (!InitFuncs.empty()) {
1195 for (auto &StartFunc : InitFuncs) {
1197 encodeULEB128(StartFunc.second, W->OS);
1198 }
1199 endSection(SubSection);
1200 }
1201
1202 if (Comdats.size()) {
1205 for (const auto &C : Comdats) {
1206 writeString(C.first);
1209 for (const WasmComdatEntry &Entry : C.second) {
1212 }
1213 }
1214 endSection(SubSection);
1215 }
1216
1217 endSection(Section);
1218}
1219
1220void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1221 const MCAssembler &Asm) {
1222 SectionBookkeeping Section;
1223 auto *Sec = CustomSection.Section;
1224 startCustomSection(Section, CustomSection.Name);
1225
1226 Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1227 Asm.writeSectionData(W->OS, Sec);
1228
1229 CustomSection.OutputContentsOffset = Section.ContentsOffset;
1230 CustomSection.OutputIndex = Section.Index;
1231
1232 endSection(Section);
1233
1234
1235 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1236 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Asm);
1237}
1238
1239uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
1241 assert(TypeIndices.count(&Symbol));
1242 return TypeIndices[&Symbol];
1243}
1244
1245uint32_t WasmObjectWriter::getTagType(const MCSymbolWasm &Symbol) {
1247 assert(TypeIndices.count(&Symbol));
1248 return TypeIndices[&Symbol];
1249}
1250
1251void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
1253
1254 wasm::WasmSignature S;
1255
1256 if (auto *Sig = Symbol.getSignature()) {
1257 S.Returns = Sig->Returns;
1258 S.Params = Sig->Params;
1259 }
1260
1261 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1262 if (Pair.second)
1263 Signatures.push_back(S);
1264 TypeIndices[&Symbol] = Pair.first->second;
1265
1266 LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
1267 << " new:" << Pair.second << "\n");
1268 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
1269}
1270
1271void WasmObjectWriter::registerTagType(const MCSymbolWasm &Symbol) {
1273
1274
1275
1276 wasm::WasmSignature S;
1277 if (auto *Sig = Symbol.getSignature()) {
1278 S.Returns = Sig->Returns;
1279 S.Params = Sig->Params;
1280 }
1281
1282 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1283 if (Pair.second)
1284 Signatures.push_back(S);
1285 TypeIndices[&Symbol] = Pair.first->second;
1286
1287 LLVM_DEBUG(dbgs() << "registerTagType: " << Symbol << " new:" << Pair.second
1288 << "\n");
1289 LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
1290}
1291
1294 return true;
1295
1297 return false;
1298
1300 return false;
1301
1303 return false;
1304
1306 return false;
1307
1308 return true;
1309}
1310
1313
1314 for (const MCSymbol &S : Asm.symbols()) {
1315 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1316 if (WS.isData() && WS.isInSection()) {
1317 auto &RefSection = static_cast<MCSectionWasm &>(WS.getSection());
1318 if (RefSection.getName() == SectionName) {
1319 return true;
1320 }
1321 }
1322 }
1323
1324 return false;
1325}
1326
1327void WasmObjectWriter::prepareImports(
1328 SmallVectorImplwasm::WasmImport &Imports, MCAssembler &Asm) {
1329
1330
1331
1332 wasm::WasmImport MemImport;
1333 MemImport.Module = "env";
1334 MemImport.Field = "__linear_memory";
1339
1340
1341
1342
1343 for (const MCSymbol &S : Asm.symbols()) {
1344 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1345
1346
1347
1348 if (WS.isFunction()) {
1349 auto *BS = static_cast<const MCSymbolWasm *>(Asm.getBaseSymbol(S));
1350 if (!BS)
1352 ": absolute addressing not supported!");
1353 registerFunctionType(*BS);
1354 }
1355
1356 if (WS.isTag())
1357 registerTagType(WS);
1358
1359 if (WS.isTemporary())
1360 continue;
1361
1362
1363 if (!WS.isDefined() && !WS.isComdat()) {
1364 if (WS.isFunction()) {
1365 wasm::WasmImport Import;
1366 Import.Module = WS.getImportModule();
1367 Import.Field = WS.getImportName();
1369 Import.SigIndex = getFunctionType(WS);
1371 assert(WasmIndices.count(&WS) == 0);
1372 WasmIndices[&WS] = NumFunctionImports++;
1373 } else if (WS.isGlobal()) {
1374 if (WS.isWeak())
1376
1377 wasm::WasmImport Import;
1378 Import.Field = WS.getImportName();
1380 Import.Module = WS.getImportModule();
1381 Import.Global = WS.getGlobalType();
1383 assert(WasmIndices.count(&WS) == 0);
1384 WasmIndices[&WS] = NumGlobalImports++;
1385 } else if (WS.isTag()) {
1386 if (WS.isWeak())
1388
1389 wasm::WasmImport Import;
1390 Import.Module = WS.getImportModule();
1391 Import.Field = WS.getImportName();
1393 Import.SigIndex = getTagType(WS);
1395 assert(WasmIndices.count(&WS) == 0);
1396 WasmIndices[&WS] = NumTagImports++;
1397 } else if (WS.isTable()) {
1398 if (WS.isWeak())
1400
1401 wasm::WasmImport Import;
1402 Import.Module = WS.getImportModule();
1403 Import.Field = WS.getImportName();
1405 Import.Table = WS.getTableType();
1407 assert(WasmIndices.count(&WS) == 0);
1408 WasmIndices[&WS] = NumTableImports++;
1409 }
1410 }
1411 }
1412
1413
1414 for (const MCSymbol &S : Asm.symbols()) {
1415 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1416 if (WS.isUsedInGOT()) {
1417 wasm::WasmImport Import;
1418 if (WS.isFunction())
1419 Import.Module = "GOT.func";
1420 else
1421 Import.Module = "GOT.mem";
1422 Import.Field = WS.getName();
1426 assert(GOTIndices.count(&WS) == 0);
1427 GOTIndices[&WS] = NumGlobalImports++;
1428 }
1429 }
1430}
1431
1432uint64_t WasmObjectWriter::writeObject() {
1434 W = &MainWriter;
1435 if (IsSplitDwarf) {
1436 uint64_t TotalSize = writeOneObject(*Asm, DwoMode::NonDwoOnly);
1439 W = &DwoWriter;
1440 return TotalSize + writeOneObject(*Asm, DwoMode::DwoOnly);
1441 } else {
1442 return writeOneObject(*Asm, DwoMode::AllSections);
1443 }
1444}
1445
1446uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
1447 DwoMode Mode) {
1448 uint64_t StartOffset = W->OS.tell();
1449 SectionCount = 0;
1450 CustomSections.clear();
1451
1452 LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
1453
1454
1456 SmallVector<uint32_t, 4> TableElems;
1464 std::map<StringRef, std::vector> Comdats;
1466 if (Mode != DwoMode::DwoOnly)
1467 prepareImports(Imports, Asm);
1468
1469
1470
1471 for (MCSection &Sec : Asm) {
1472 auto &Section = static_cast<MCSectionWasm &>(Sec);
1474
1476 continue;
1478 continue;
1479
1480 LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group "
1481 << Section.getGroup() << "\n";);
1482
1483
1484
1485 if (SectionName.starts_with(".init_array") &&
1487 continue;
1488
1489
1491 continue;
1492
1493 if (Section.isWasmData()) {
1494 uint32_t SegmentIndex = DataSegments.size();
1496 DataSegments.emplace_back();
1497 WasmDataSegment &Segment = DataSegments.back();
1499 Segment.InitFlags = Section.getPassive()
1501 : 0;
1503 Segment.Section = &Section;
1504 addData(Segment.Data, Section);
1505 Segment.Alignment = Log2(Section.getAlign());
1506 Segment.LinkingFlags = Section.getSegmentFlags();
1507 DataSize += Segment.Data.size();
1508 Section.setSegmentIndex(SegmentIndex);
1509
1510 if (const MCSymbolWasm *C = Section.getGroup()) {
1511 Comdats[C->getName()].emplace_back(
1513 }
1514 } else {
1515
1517
1519
1520
1521 Name.consume_front(".custom_section.");
1522
1523 auto *Begin = static_cast<MCSymbolWasm *>(Sec.getBeginSymbol());
1524 if (Begin) {
1525 assert(WasmIndices.count(Begin) == 0);
1526 WasmIndices[Begin] = CustomSections.size();
1527 }
1528
1529
1530 if (Name == "producers") {
1531 ProducersSection = std::make_unique(Name, &Section);
1532 continue;
1533 }
1534 if (Name == "target_features") {
1535 TargetFeaturesSection =
1536 std::make_unique(Name, &Section);
1537 continue;
1538 }
1539
1540
1541
1542
1543
1544 if (const MCSymbolWasm *C = Section.getGroup()) {
1545 Comdats[C->getName()].emplace_back(
1547 static_cast<uint32_t>(CustomSections.size())});
1548 }
1549
1550 CustomSections.emplace_back(Name, &Section);
1551 }
1552 }
1553
1554 if (Mode != DwoMode::DwoOnly) {
1555
1556 for (const MCSymbol &S : Asm.symbols()) {
1557
1558
1559 if (S.isTemporary() && S.getName().empty())
1560 continue;
1561
1562 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1564 dbgs() << "MCSymbol: "
1566 << " '" << S << "'"
1567 << " isDefined=" << S.isDefined() << " isExternal="
1568 << WS.isExternal() << " isTemporary=" << S.isTemporary()
1569 << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
1570 << " isVariable=" << WS.isVariable() << "\n");
1571
1572 if (WS.isVariable())
1573 continue;
1574 if (WS.isComdat() && !WS.isDefined())
1575 continue;
1576
1577 if (WS.isFunction()) {
1579 if (WS.isDefined()) {
1580 if (WS.getOffset() != 0)
1582 "function sections must contain one function each");
1583
1584
1585 Index = NumFunctionImports + Functions.size();
1586 WasmFunction Func;
1587 Func.SigIndex = getFunctionType(WS);
1588 Func.Section = &WS.getSection();
1589 assert(WasmIndices.count(&WS) == 0);
1590 WasmIndices[&WS] = Index;
1592
1593 auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
1594 if (const MCSymbolWasm *C = Section.getGroup()) {
1595 Comdats[C->getName()].emplace_back(
1597 }
1598
1599 if (WS.hasExportName()) {
1600 wasm::WasmExport Export;
1601 Export.Name = WS.getExportName();
1605 }
1606 } else {
1607
1608 Index = WasmIndices.find(&WS)->second;
1609 }
1610
1611 LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
1612
1613 } else if (WS.isData()) {
1615 continue;
1616
1617 if (!WS.isDefined()) {
1619 << "\n");
1620 continue;
1621 }
1622
1623 if (!WS.getSize())
1624 report_fatal_error("data symbols must have a size set with .size: " +
1625 WS.getName());
1626
1627 int64_t Size = 0;
1628 if (!WS.getSize()->evaluateAsAbsolute(Size, Asm))
1630
1631 auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1632 if (!DataSection.isWasmData())
1634 WS.getName());
1635
1636
1637
1638 wasm::WasmDataReference Ref = wasm::WasmDataReference{
1639 DataSection.getSegmentIndex(), Asm.getSymbolOffset(WS),
1640 static_cast<uint64_t>(Size)};
1641 assert(DataLocations.count(&WS) == 0);
1642 DataLocations[&WS] = Ref;
1643 LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
1644
1645 } else if (WS.isGlobal()) {
1646
1647 if (WS.isDefined()) {
1648 wasm::WasmGlobal Global;
1649 Global.Type = WS.getGlobalType();
1650 Global.Index = NumGlobalImports + Globals.size();
1651 Global.InitExpr.Extended = false;
1652 switch (Global.Type.Type) {
1655 break;
1658 break;
1661 break;
1664 break;
1667 break;
1668 default:
1670 }
1671 assert(WasmIndices.count(&WS) == 0);
1672 WasmIndices[&WS] = Global.Index;
1674 } else {
1675
1677 << WasmIndices.find(&WS)->second << "\n");
1678 }
1679 } else if (WS.isTable()) {
1680 if (WS.isDefined()) {
1681 wasm::WasmTable Table;
1682 Table.Index = NumTableImports + Tables.size();
1683 Table.Type = WS.getTableType();
1684 assert(WasmIndices.count(&WS) == 0);
1685 WasmIndices[&WS] = Table.Index;
1687 }
1689 << WasmIndices.find(&WS)->second << "\n");
1690 } else if (WS.isTag()) {
1691
1692
1694 if (WS.isDefined()) {
1695 Index = NumTagImports + TagTypes.size();
1696 uint32_t SigIndex = getTagType(WS);
1697 assert(WasmIndices.count(&WS) == 0);
1698 WasmIndices[&WS] = Index;
1700 } else {
1701
1702 assert(WasmIndices.count(&WS) > 0);
1703 }
1704 LLVM_DEBUG(dbgs() << " -> tag index: " << WasmIndices.find(&WS)->second
1705 << "\n");
1706
1707 } else {
1708 assert(WS.isSection());
1709 }
1710 }
1711
1712
1713
1714
1715
1716 for (const MCSymbol &S : Asm.symbols()) {
1717 if (!S.isVariable())
1718 continue;
1719
1720 assert(S.isDefined());
1721
1722 const auto *BS = Asm.getBaseSymbol(S);
1723 if (!BS)
1725 ": absolute addressing not supported!");
1726 const MCSymbolWasm *Base = static_cast<const MCSymbolWasm *>(BS);
1727
1728
1729 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1731 << "'\n");
1732
1733 if (Base->isFunction()) {
1734 assert(WasmIndices.count(Base) > 0);
1735 uint32_t WasmIndex = WasmIndices.find(Base)->second;
1736 assert(WasmIndices.count(&WS) == 0);
1737 WasmIndices[&WS] = WasmIndex;
1738 LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
1739 } else if (Base->isData()) {
1740 auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1741 uint64_t Offset = Asm.getSymbolOffset(S);
1742 int64_t Size = 0;
1743
1744
1745
1746
1747 if (->getSize()->evaluateAsAbsolute(Size, Asm))
1749 const WasmDataSegment &Segment =
1750 DataSegments[DataSection.getSegmentIndex()];
1752 std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);
1753 wasm::WasmDataReference Ref = wasm::WasmDataReference{
1754 DataSection.getSegmentIndex(),
1755 static_cast<uint32_t>(Asm.getSymbolOffset(S)),
1756 static_cast<uint32_t>(Size)};
1757 DataLocations[&WS] = Ref;
1759 } else {
1761 }
1762 }
1763 }
1764
1765
1766 for (const MCSymbol &S : Asm.symbols()) {
1767 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1770 continue;
1771 }
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782 if (WS.isData() && WS.isDefined() && !DataLocations.count(&WS))
1783 continue;
1784 LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
1785
1786 uint32_t Flags = 0;
1787 if (WS.isWeak())
1789 if (WS.isHidden())
1791 if (!WS.isExternal() && WS.isDefined())
1793 if (WS.isUndefined())
1795 if (WS.isNoStrip()) {
1797 if (isEmscripten()) {
1799 }
1800 }
1801 if (WS.hasImportName())
1803 if (WS.hasExportName())
1805 if (WS.isTLS())
1807
1808 wasm::WasmSymbolInfo Info;
1809 Info.Name = WS.getName();
1812 if (!WS.isData()) {
1813 assert(WasmIndices.count(&WS) > 0);
1814 Info.ElementIndex = WasmIndices.find(&WS)->second;
1815 } else if (WS.isDefined()) {
1816 assert(DataLocations.count(&WS) > 0);
1817 Info.DataRef = DataLocations.find(&WS)->second;
1818 }
1819 WS.setIndex(SymbolInfos.size());
1821 }
1822
1823 {
1824 auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
1825
1826
1827
1828 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1829 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1830 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1831 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1832 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1833 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1834 return;
1835 assert(Rel.Symbol->isFunction());
1836 auto *Base =
1837 static_cast<const MCSymbolWasm *>(Asm.getBaseSymbol(*Rel.Symbol));
1838 uint32_t FunctionIndex = WasmIndices.find(Base)->second;
1839 uint32_t TableIndex = TableElems.size() + InitialTableOffset;
1840 if (TableIndices.try_emplace(Base, TableIndex).second) {
1842 << " to table: " << TableIndex << "\n");
1843 TableElems.push_back(FunctionIndex);
1844 registerFunctionType(*Base);
1845 }
1846 };
1847
1848 for (const WasmRelocationEntry &RelEntry : CodeRelocations)
1849 HandleReloc(RelEntry);
1850 for (const WasmRelocationEntry &RelEntry : DataRelocations)
1851 HandleReloc(RelEntry);
1852 }
1853
1854
1855 for (const MCSection &S : Asm) {
1856 const auto &WS = static_cast<const MCSectionWasm &>(S);
1857 if (WS.getName().starts_with(".fini_array"))
1859 if (!WS.getName().starts_with(".init_array"))
1860 continue;
1861 auto IT = WS.begin();
1862 if (IT == WS.end())
1863 continue;
1864 for (auto *Frag = &*IT; Frag; Frag = Frag->getNext()) {
1868
1869 uint16_t Priority = UINT16_MAX;
1870 unsigned PrefixLength = strlen(".init_array");
1871 if (WS.getName().size() > PrefixLength) {
1872 if (WS.getName()[PrefixLength] != '.')
1874 ".init_array section priority should start with '.'");
1875 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1877 }
1879 for (const MCFixup &Fixup : Frag->getFixups()) {
1882 const MCExpr *Expr = Fixup.getValue();
1884 if (!SymRef)
1886 "fixups in .init_array should be symbol references");
1887 auto &TargetSym =
1888 static_cast<const MCSymbolWasm &>(SymRef->getSymbol());
1890 report_fatal_error("symbols in .init_array should exist in symtab");
1891 if (!TargetSym.isFunction())
1892 report_fatal_error("symbols in .init_array should be for functions");
1893 InitFuncs.push_back(std::make_pair(Priority, TargetSym.getIndex()));
1894 }
1895 }
1896 }
1897
1898
1899 writeHeader(Asm);
1900
1901 uint32_t CodeSectionIndex, DataSectionIndex;
1902 if (Mode != DwoMode::DwoOnly) {
1903 writeTypeSection(Signatures);
1904 writeImportSection(Imports, DataSize, TableElems.size());
1905 writeFunctionSection(Functions);
1906 writeTableSection(Tables);
1907
1908 writeTagSection(TagTypes);
1909 writeGlobalSection(Globals);
1910 writeExportSection(Exports);
1911 const MCSymbol *IndirectFunctionTable =
1912 getContext().lookupSymbol("__indirect_function_table");
1913 writeElemSection(static_cast<const MCSymbolWasm *>(IndirectFunctionTable),
1914 TableElems);
1915 writeDataCountSection();
1916
1917 CodeSectionIndex = writeCodeSection(Asm, Functions);
1918 DataSectionIndex = writeDataSection(Asm);
1919 }
1920
1921
1922
1923 for (auto &Group : Comdats) {
1924 for (auto &Entry : Group.second) {
1926 Entry.Index += SectionCount;
1927 }
1928 }
1929 }
1930 for (auto &CustomSection : CustomSections)
1931 writeCustomSection(CustomSection, Asm);
1932
1933 if (Mode != DwoMode::DwoOnly) {
1934 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1935
1936 writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
1937 writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
1938 }
1939 writeCustomRelocSections();
1940 if (ProducersSection)
1941 writeCustomSection(*ProducersSection, Asm);
1942 if (TargetFeaturesSection)
1943 writeCustomSection(*TargetFeaturesSection, Asm);
1944
1945
1946 return W->OS.tell() - StartOffset;
1947}
1948
1949std::unique_ptr
1952 return std::make_unique(std::move(MOTW), OS);
1953}
1954
1955std::unique_ptr
1959 return std::make_unique(std::move(MOTW), OS, DwoOS);
1960}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
PowerPC TLS Dynamic Call Fixup
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static const unsigned InvalidIndex
static bool isSectionReferenced(MCAssembler &Asm, MCSectionWasm &Section)
Definition WasmObjectWriter.cpp:1311
static void addData(SmallVectorImpl< char > &DataBytes, MCSectionWasm &DataSection)
Definition WasmObjectWriter.cpp:693
static bool isInSymtab(const MCSymbolWasm &Sym)
Definition WasmObjectWriter.cpp:1292
static bool isDwoSection(const MCSection &Sec)
static bool is64Bit(const char *name)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
LLVM_ABI MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
static MCFixupKind getDataKindForSize(unsigned Size)
Return the generic fixup kind for a value with the given size.
Defines the object file and target independent interfaces used by the assembler backend to write nati...
virtual void reset()
lifetime management
This represents a section on wasm.
uint64_t getSectionOffset() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
StringRef getName() const
MCSymbol * getBeginSymbol()
bool omitFromLinkingSection() const
bool isUsedInInitArray() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
StringRef getName() const
getName - Get the symbol name.
uint32_t getIndex() const
Get the (implementation defined) index.
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
bool isUsedInReloc() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & write(unsigned char C)
An abstract base class for streams implementations that also support a pwrite operation.
void pwrite(const char *Ptr, size_t Size, uint64_t Offset)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ C
The default llvm calling convention, compatible with C.
bool isRelocRelocation(MCFixupKind FixupKind)
NodeAddr< FuncNode * > Func
Context & getContext() const
void write64le(void *P, uint64_t V)
void write32le(void *P, uint32_t V)
const unsigned WASM_SYMBOL_UNDEFINED
const unsigned WASM_SYMBOL_NO_STRIP
const unsigned WASM_SYMBOL_TLS
const uint32_t WasmMetadataVersion
const unsigned WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_LOCAL
@ 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
const uint32_t WasmVersion
const unsigned WASM_SYMBOL_EXPORTED
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
LLVM_ABI bool relocTypeHasAddend(uint32_t type)
const uint32_t WasmDefaultPageSize
const unsigned WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
LLVM_ABI llvm::StringRef relocTypetoString(uint32_t type)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
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.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
FunctionAddr VTableAddr uintptr_t uintptr_t DataSize
std::unique_ptr< MCObjectWriter > createWasmObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Construct a new Wasm writer instance.
Definition WasmObjectWriter.cpp:1950
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
@ FirstLiteralRelocationKind
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
unsigned Log2(Align A)
Returns the log2 of the alignment.
std::unique_ptr< MCObjectWriter > createWasmDwoObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS)
Definition WasmObjectWriter.cpp:1956
Adapter to write values to a stream in a particular byte order.
void write(ArrayRef< value_type > Val)
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params