16 #include "llvm/Config/llvm-config.h"
37 #define DEBUG_TYPE "mc"
43 static const uint32_t InitialTableOffset = 1;
48 struct SectionBookkeeping {
62 struct WasmDataSegment {
87 struct WasmComdatEntry {
93 struct WasmRelocationEntry {
101 int64_t Addend,
unsigned Type,
104 FixupSection(FixupSection) {}
110 <<
", Sym=" << *
Symbol <<
", Addend=" << Addend
111 <<
", FixupSection=" << FixupSection->
getName();
114 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
121 struct WasmCustomSection {
142 template <
typename T,
int W>
147 Stream.pwrite((
char *)Buffer, SizeLen, Offset);
152 template <
typename T,
int W>
157 Stream.pwrite((
char *)Buffer, SizeLen, Offset);
162 writePatchableULEB<uint32_t, 5>(Stream,
Value, Offset);
167 writePatchableSLEB<int32_t, 5>(Stream,
Value, Offset);
172 writePatchableSLEB<uint64_t, 10>(Stream,
Value, Offset);
177 writePatchableSLEB<int64_t, 10>(Stream,
Value, Offset);
185 Stream.pwrite((
char *)Buffer,
sizeof(Buffer), Offset);
192 Stream.pwrite((
char *)Buffer,
sizeof(Buffer), Offset);
195 bool isDwoSection(
const MCSection &Sec) {
203 std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
206 std::vector<WasmRelocationEntry> CodeRelocations;
208 std::vector<WasmRelocationEntry> DataRelocations;
225 std::vector<WasmCustomSection> CustomSections;
226 std::unique_ptr<WasmCustomSection> ProducersSection;
227 std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
230 CustomSectionsRelocations;
238 unsigned NumFunctionImports = 0;
239 unsigned NumGlobalImports = 0;
240 unsigned NumTableImports = 0;
241 unsigned NumTagImports = 0;
249 bool IsSplitDwarf =
false;
254 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
255 bool isEmscripten()
const {
return TargetObjectWriter->isEmscripten(); }
257 void startSection(SectionBookkeeping &Section,
unsigned SectionId);
258 void startCustomSection(SectionBookkeeping &Section,
StringRef Name);
259 void endSection(SectionBookkeeping &Section);
262 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
264 : TargetObjectWriter(
std::move(MOTW)), OS(&OS_) {}
266 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
268 : TargetObjectWriter(
std::move(MOTW)), IsSplitDwarf(
true), OS(&OS_),
272 void reset()
override {
273 CodeRelocations.clear();
274 DataRelocations.clear();
278 TableIndices.
clear();
279 DataLocations.
clear();
280 CustomSections.clear();
281 ProducersSection.reset();
282 TargetFeaturesSection.reset();
283 CustomSectionsRelocations.
clear();
284 SignatureIndices.
clear();
286 DataSegments.
clear();
287 SectionFunctions.
clear();
288 NumFunctionImports = 0;
289 NumGlobalImports = 0;
314 void writeStringWithAlignment(
const StringRef Str,
unsigned Alignment);
316 void writeI32(int32_t
val) {
319 W->OS.write(Buffer,
sizeof(Buffer));
322 void writeI64(int64_t
val) {
325 W->OS.write(Buffer,
sizeof(Buffer));
328 void writeValueType(
wasm::ValType Ty) {
W->OS <<
static_cast<char>(Ty); }
335 void writeElemSection(
const MCSymbolWasm *IndirectFunctionTable,
337 void writeDataCountSection();
345 std::vector<WasmRelocationEntry> &Relocations);
346 void writeLinkingMetaDataSection(
348 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
349 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats);
350 void writeCustomSection(WasmCustomSection &CustomSection,
352 void writeCustomRelocSections();
354 uint64_t getProvisionalValue(
const WasmRelocationEntry &RelEntry,
359 uint32_t getRelocationIndexValue(
const WasmRelocationEntry &RelEntry);
369 void WasmObjectWriter::startSection(SectionBookkeeping &Section,
370 unsigned SectionId) {
372 W->OS << char(SectionId);
381 Section.ContentsOffset =
W->OS.tell();
382 Section.PayloadOffset =
W->OS.tell();
383 Section.Index = SectionCount++;
388 void WasmObjectWriter::writeStringWithAlignment(
const StringRef Str,
389 unsigned Alignment) {
400 assert((StrSizeLength + Paddings) <= 5 &&
"too long string to align");
405 assert(
W->OS.tell() == Offset &&
"invalid padding");
408 void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
414 Section.PayloadOffset =
W->OS.tell();
417 if (
Name !=
"__clangast") {
421 writeStringWithAlignment(
Name, 4);
425 Section.ContentsOffset =
W->OS.tell();
430 void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
463 if (
auto *Sym =
Asm.getContext().lookupSymbol(
"__indirect_function_table")) {
464 const auto *WasmSym =
static_cast<const MCSymbolWasm *
>(Sym);
465 if (WasmSym->isNoStrip())
466 Asm.registerSymbol(*Sym);
473 if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
474 const auto &Sec =
static_cast<const MCSectionWasm &
>(
S.getSection());
475 auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &
S));
489 assert(!(
Asm.getBackend().getFixupKindInfo(
Fixup.getKind()).Flags &
492 const auto &FixupSection = cast<MCSectionWasm>(*
Fragment->getParent());
496 bool IsLocRel =
false;
500 const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
502 if (FixupSection.getKind().isText()) {
504 Twine(
"symbol '") + SymB.getName() +
505 "' unsupported subtraction expression used in "
506 "relocation in code section.");
510 if (SymB.isUndefined()) {
512 Twine(
"symbol '") + SymB.getName() +
513 "' can not be undefined in a subtraction expression");
516 const MCSection &SecB = SymB.getSection();
517 if (&SecB != &FixupSection) {
519 Twine(
"symbol '") + SymB.getName() +
520 "' can not be placed in a different section");
529 const auto *SymA = cast<MCSymbolWasm>(&RefA->
getSymbol());
532 if (FixupSection.getName().startswith(
".init_array")) {
533 SymA->setUsedInInitArray();
537 if (SymA->isVariable()) {
538 const MCExpr *Expr = SymA->getVariableValue();
539 if (
const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr))
550 TargetObjectWriter->getRelocType(
Target, Fixup, FixupSection, IsLocRel);
555 if ((
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
556 Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
557 Type == wasm::R_WASM_SECTION_OFFSET_I32) &&
564 if (!FixupSection.getKind().isMetadata())
566 "only supported in metadata sections");
568 const MCSymbol *SectionSymbol =
nullptr;
569 const MCSection &SecA = SymA->getSection();
571 auto SecSymIt = SectionFunctions.find(&SecA);
572 if (SecSymIt == SectionFunctions.end())
574 SectionSymbol = SecSymIt->second;
582 SymA = cast<MCSymbolWasm>(SectionSymbol);
585 if (
Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
586 Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 ||
587 Type == wasm::R_WASM_TABLE_INDEX_SLEB ||
588 Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||
589 Type == wasm::R_WASM_TABLE_INDEX_I32 ||
590 Type == wasm::R_WASM_TABLE_INDEX_I64) {
593 auto TableName =
"__indirect_function_table";
602 Asm.registerSymbol(*Sym);
608 if (
Type != wasm::R_WASM_TYPE_INDEX_LEB) {
609 if (SymA->getName().empty())
611 "supported by wasm");
613 SymA->setUsedInReloc();
619 SymA->setUsedInGOT();
625 WasmRelocationEntry Rec(FixupOffset, SymA,
C,
Type, &FixupSection);
628 if (FixupSection.isWasmData()) {
629 DataRelocations.push_back(Rec);
630 }
else if (FixupSection.getKind().isText()) {
631 CodeRelocations.push_back(Rec);
632 }
else if (FixupSection.getKind().isMetadata()) {
633 CustomSectionsRelocations[&FixupSection].push_back(Rec);
644 WasmObjectWriter::getProvisionalValue(
const WasmRelocationEntry &RelEntry,
646 if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
647 RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
648 !RelEntry.Symbol->isGlobal()) {
649 assert(GOTIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in GOT index space");
650 return GOTIndices[RelEntry.Symbol];
653 switch (RelEntry.Type) {
654 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
655 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
656 case wasm::R_WASM_TABLE_INDEX_SLEB:
657 case wasm::R_WASM_TABLE_INDEX_SLEB64:
658 case wasm::R_WASM_TABLE_INDEX_I32:
659 case wasm::R_WASM_TABLE_INDEX_I64: {
664 if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
665 RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
666 return TableIndices[
Base] - InitialTableOffset;
668 return TableIndices[
Base];
670 case wasm::R_WASM_TYPE_INDEX_LEB:
672 return getRelocationIndexValue(RelEntry);
673 case wasm::R_WASM_FUNCTION_INDEX_LEB:
674 case wasm::R_WASM_GLOBAL_INDEX_LEB:
675 case wasm::R_WASM_GLOBAL_INDEX_I32:
676 case wasm::R_WASM_TAG_INDEX_LEB:
677 case wasm::R_WASM_TABLE_NUMBER_LEB:
679 assert(WasmIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in wasm index space");
680 return WasmIndices[RelEntry.Symbol];
681 case wasm::R_WASM_FUNCTION_OFFSET_I32:
682 case wasm::R_WASM_FUNCTION_OFFSET_I64:
683 case wasm::R_WASM_SECTION_OFFSET_I32: {
684 if (!RelEntry.Symbol->isDefined())
687 static_cast<const MCSectionWasm &
>(RelEntry.Symbol->getSection());
688 return Section.getSectionOffset() + RelEntry.Addend;
690 case wasm::R_WASM_MEMORY_ADDR_LEB:
691 case wasm::R_WASM_MEMORY_ADDR_LEB64:
692 case wasm::R_WASM_MEMORY_ADDR_SLEB:
693 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
694 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
695 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
696 case wasm::R_WASM_MEMORY_ADDR_I32:
697 case wasm::R_WASM_MEMORY_ADDR_I64:
698 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
699 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
700 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {
703 if (!RelEntry.Symbol->isDefined())
706 const WasmDataSegment &Segment = DataSegments[SymRef.
Segment];
708 return Segment.Offset + SymRef.
Offset + RelEntry.Addend;
722 if (Frag.hasInstructions())
725 if (
auto *
Align = dyn_cast<MCAlignFragment>(&Frag)) {
726 if (
Align->getValueSize() != 1)
731 std::min<uint64_t>(
alignTo(DataBytes.size(),
Align->getAlignment()),
732 DataBytes.size() +
Align->getMaxBytesToEmit());
734 }
else if (
auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
736 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
738 DataBytes.
insert(DataBytes.end(), Fill->getValueSize() * NumValues,
740 }
else if (
auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
744 const auto &DataFrag = cast<MCDataFragment>(Frag);
754 WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
755 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
756 if (!TypeIndices.count(RelEntry.Symbol))
758 RelEntry.Symbol->getName());
759 return TypeIndices[RelEntry.Symbol];
762 return RelEntry.Symbol->getIndex();
767 void WasmObjectWriter::applyRelocations(
771 for (
const WasmRelocationEntry &RelEntry : Relocations) {
773 RelEntry.FixupSection->getSectionOffset() +
779 switch (RelEntry.Type) {
780 case wasm::R_WASM_FUNCTION_INDEX_LEB:
781 case wasm::R_WASM_TYPE_INDEX_LEB:
782 case wasm::R_WASM_GLOBAL_INDEX_LEB:
783 case wasm::R_WASM_MEMORY_ADDR_LEB:
784 case wasm::R_WASM_TAG_INDEX_LEB:
785 case wasm::R_WASM_TABLE_NUMBER_LEB:
786 writePatchableU32(Stream,
Value, Offset);
788 case wasm::R_WASM_MEMORY_ADDR_LEB64:
789 writePatchableU64(Stream,
Value, Offset);
791 case wasm::R_WASM_TABLE_INDEX_I32:
792 case wasm::R_WASM_MEMORY_ADDR_I32:
793 case wasm::R_WASM_FUNCTION_OFFSET_I32:
794 case wasm::R_WASM_SECTION_OFFSET_I32:
795 case wasm::R_WASM_GLOBAL_INDEX_I32:
796 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
797 patchI32(Stream,
Value, Offset);
799 case wasm::R_WASM_TABLE_INDEX_I64:
800 case wasm::R_WASM_MEMORY_ADDR_I64:
801 case wasm::R_WASM_FUNCTION_OFFSET_I64:
802 patchI64(Stream,
Value, Offset);
804 case wasm::R_WASM_TABLE_INDEX_SLEB:
805 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
806 case wasm::R_WASM_MEMORY_ADDR_SLEB:
807 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
808 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
809 writePatchableS32(Stream,
Value, Offset);
811 case wasm::R_WASM_TABLE_INDEX_SLEB64:
812 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
813 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
814 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
815 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
816 writePatchableS64(Stream,
Value, Offset);
824 void WasmObjectWriter::writeTypeSection(
826 if (Signatures.
empty())
860 writeString(
Import.Module);
861 writeString(
Import.Field);
869 W->OS << char(
Import.Global.Type);
870 W->OS << char(
Import.Global.Mutable ? 1 : 0);
877 W->OS << char(
Import.Table.ElemType);
894 if (Functions.
empty())
901 for (
const WasmFunction &Func : Functions)
908 if (TagTypes.
empty())
933 W->OS << char(
Global.Type.Mutable);
934 if (
Global.InitExpr.Extended) {
937 W->OS << char(
Global.InitExpr.Inst.Opcode);
938 switch (
Global.Type.Type) {
999 void WasmObjectWriter::writeElemSection(
1001 if (TableElems.
empty())
1004 assert(IndirectFunctionTable);
1011 assert(WasmIndices.count(IndirectFunctionTable));
1012 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
1028 const uint8_t ElemKind = 0;
1036 endSection(Section);
1039 void WasmObjectWriter::writeDataCountSection() {
1040 if (DataSegments.empty())
1046 endSection(Section);
1052 if (Functions.
empty())
1060 for (
const WasmFunction &Func : Functions) {
1064 if (!
Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
1068 FuncSection.setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1069 Asm.writeSectionData(
W->OS, &FuncSection, Layout);
1073 applyRelocations(CodeRelocations,
Section.ContentsOffset, Layout);
1075 endSection(Section);
1080 if (DataSegments.empty())
1088 for (
const WasmDataSegment &Segment : DataSegments) {
1099 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1100 W->OS << Segment.Data;
1104 applyRelocations(DataRelocations,
Section.ContentsOffset, Layout);
1106 endSection(Section);
1110 void WasmObjectWriter::writeRelocSection(
1112 std::vector<WasmRelocationEntry> &Relocs) {
1125 Relocs, [](
const WasmRelocationEntry &A,
const WasmRelocationEntry &
B) {
1126 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1127 (
B.Offset +
B.FixupSection->getSectionOffset());
1131 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1135 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1137 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1140 W->OS << char(RelEntry.Type);
1143 if (RelEntry.hasAddend())
1147 endSection(Section);
1150 void WasmObjectWriter::writeCustomRelocSections() {
1151 for (
const auto &Sec : CustomSections) {
1152 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1153 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1157 void WasmObjectWriter::writeLinkingMetaDataSection(
1159 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1160 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1162 startCustomSection(Section,
"linking");
1165 SectionBookkeeping SubSection;
1166 if (SymbolInfos.
size() != 0) {
1180 writeString(Sym.Name);
1183 writeString(Sym.Name);
1192 CustomSections[Sym.ElementIndex].OutputIndex;
1200 endSection(SubSection);
1203 if (DataSegments.size()) {
1206 for (
const WasmDataSegment &Segment : DataSegments) {
1207 writeString(Segment.Name);
1211 endSection(SubSection);
1214 if (!InitFuncs.empty()) {
1217 for (
auto &StartFunc : InitFuncs) {
1221 endSection(SubSection);
1224 if (Comdats.size()) {
1227 for (
const auto &
C : Comdats) {
1228 writeString(
C.first);
1231 for (
const WasmComdatEntry &Entry :
C.second) {
1236 endSection(SubSection);
1239 endSection(Section);
1242 void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1246 auto *Sec = CustomSection.Section;
1247 startCustomSection(Section, CustomSection.Name);
1249 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1250 Asm.writeSectionData(
W->OS, Sec, Layout);
1252 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1253 CustomSection.OutputIndex =
Section.Index;
1255 endSection(Section);
1258 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1259 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
1265 return TypeIndices[&
Symbol];
1271 return TypeIndices[&
Symbol];
1279 if (
auto *Sig =
Symbol.getSignature()) {
1280 S.Returns = Sig->Returns;
1281 S.Params = Sig->Params;
1284 auto Pair = SignatureIndices.insert(std::make_pair(
S, Signatures.size()));
1286 Signatures.push_back(
S);
1287 TypeIndices[&
Symbol] = Pair.first->second;
1290 <<
" new:" << Pair.second <<
"\n");
1291 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1300 if (
auto *Sig =
Symbol.getSignature()) {
1301 S.Returns = Sig->Returns;
1302 S.Params = Sig->Params;
1305 auto Pair = SignatureIndices.insert(std::make_pair(
S, Signatures.size()));
1307 Signatures.push_back(
S);
1308 TypeIndices[&
Symbol] = Pair.first->second;
1312 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1334 void WasmObjectWriter::prepareImports(
1341 MemImport.
Module =
"env";
1342 MemImport.
Field =
"__linear_memory";
1346 Imports.push_back(MemImport);
1356 if (WS.isFunction()) {
1360 ": absolute addressing not supported!");
1361 registerFunctionType(*cast<MCSymbolWasm>(BS));
1365 registerTagType(WS);
1367 if (WS.isTemporary())
1371 if (!WS.isDefined() && !WS.isComdat()) {
1372 if (WS.isFunction()) {
1374 Import.Module = WS.getImportModule();
1375 Import.Field = WS.getImportName();
1377 Import.SigIndex = getFunctionType(WS);
1378 Imports.push_back(Import);
1379 assert(WasmIndices.count(&WS) == 0);
1380 WasmIndices[&WS] = NumFunctionImports++;
1381 }
else if (WS.isGlobal()) {
1386 Import.Field = WS.getImportName();
1388 Import.Module = WS.getImportModule();
1389 Import.Global = WS.getGlobalType();
1390 Imports.push_back(Import);
1391 assert(WasmIndices.count(&WS) == 0);
1392 WasmIndices[&WS] = NumGlobalImports++;
1393 }
else if (WS.isTag()) {
1398 Import.Module = WS.getImportModule();
1399 Import.Field = WS.getImportName();
1401 Import.SigIndex = getTagType(WS);
1402 Imports.push_back(Import);
1403 assert(WasmIndices.count(&WS) == 0);
1404 WasmIndices[&WS] = NumTagImports++;
1405 }
else if (WS.isTable()) {
1410 Import.Module = WS.getImportModule();
1411 Import.Field = WS.getImportName();
1413 Import.Table = WS.getTableType();
1414 Imports.push_back(Import);
1415 assert(WasmIndices.count(&WS) == 0);
1416 WasmIndices[&WS] = NumTableImports++;
1424 if (WS.isUsedInGOT()) {
1426 if (WS.isFunction())
1427 Import.Module =
"GOT.func";
1429 Import.Module =
"GOT.mem";
1430 Import.Field = WS.getName();
1433 Imports.push_back(Import);
1434 assert(GOTIndices.count(&WS) == 0);
1435 GOTIndices[&WS] = NumGlobalImports++;
1445 uint64_t TotalSize = writeOneObject(
Asm, Layout, DwoMode::NonDwoOnly);
1449 return TotalSize + writeOneObject(
Asm, Layout, DwoMode::DwoOnly);
1451 return writeOneObject(
Asm, Layout, DwoMode::AllSections);
1460 CustomSections.clear();
1474 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1476 if (
Mode != DwoMode::DwoOnly) {
1477 prepareImports(Imports,
Asm, Layout);
1486 if (
Mode == DwoMode::NonDwoOnly && isDwoSection(Sec))
1488 if (
Mode == DwoMode::DwoOnly && !isDwoSection(Sec))
1492 <<
Section.getGroup() <<
"\n";);
1499 if (
Section.getKind().isText())
1503 uint32_t SegmentIndex = DataSegments.size();
1505 DataSegments.emplace_back();
1506 WasmDataSegment &Segment = DataSegments.back();
1508 Segment.InitFlags =
Section.getPassive()
1511 Segment.Offset = DataSize;
1513 addData(Segment.Data, Section);
1515 Segment.LinkingFlags =
Section.getSegmentFlags();
1516 DataSize += Segment.Data.size();
1517 Section.setSegmentIndex(SegmentIndex);
1520 Comdats[
C->getName()].emplace_back(
1525 assert(Sec.getKind().isMetadata());
1530 if (
Name.startswith(
".custom_section."))
1531 Name =
Name.substr(strlen(
".custom_section."));
1533 MCSymbol *Begin = Sec.getBeginSymbol();
1535 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1536 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1540 if (
Name ==
"producers") {
1541 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &Section);
1544 if (
Name ==
"target_features") {
1545 TargetFeaturesSection =
1546 std::make_unique<WasmCustomSection>(
Name, &Section);
1555 Comdats[
C->getName()].emplace_back(
1557 static_cast<uint32_t>(CustomSections.size())});
1560 CustomSections.emplace_back(
Name, &Section);
1564 if (
Mode != DwoMode::DwoOnly) {
1569 if (
S.isTemporary() &&
S.getName().empty())
1577 <<
" isDefined=" <<
S.isDefined() <<
" isExternal="
1578 <<
S.isExternal() <<
" isTemporary=" <<
S.isTemporary()
1579 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1580 <<
" isVariable=" << WS.isVariable() <<
"\n");
1582 if (WS.isVariable())
1584 if (WS.isComdat() && !WS.isDefined())
1587 if (WS.isFunction()) {
1589 if (WS.isDefined()) {
1590 if (WS.getOffset() != 0)
1592 "function sections must contain one function each");
1594 if (WS.getSize() ==
nullptr)
1596 "function symbols must have a size set with .size");
1599 Index = NumFunctionImports + Functions.size();
1601 Func.SigIndex = getFunctionType(WS);
1603 assert(WasmIndices.count(&WS) == 0);
1604 WasmIndices[&WS] =
Index;
1605 Functions.push_back(Func);
1609 Comdats[
C->getName()].emplace_back(
1613 if (WS.hasExportName()) {
1615 Export.Name = WS.getExportName();
1618 Exports.push_back(Export);
1622 Index = WasmIndices.find(&WS)->second;
1627 }
else if (WS.isData()) {
1631 if (!WS.isDefined()) {
1642 if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
1645 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1646 if (!DataSection.isWasmData())
1655 assert(DataLocations.count(&WS) == 0);
1656 DataLocations[&WS] =
Ref;
1659 }
else if (WS.isGlobal()) {
1661 if (WS.isDefined()) {
1663 Global.Type = WS.getGlobalType();
1664 Global.Index = NumGlobalImports + Globals.size();
1665 Global.InitExpr.Extended =
false;
1666 switch (
Global.Type.Type) {
1685 assert(WasmIndices.count(&WS) == 0);
1686 WasmIndices[&WS] =
Global.Index;
1687 Globals.push_back(Global);
1691 << WasmIndices.find(&WS)->second <<
"\n");
1693 }
else if (WS.isTable()) {
1694 if (WS.isDefined()) {
1696 Table.
Index = NumTableImports + Tables.size();
1697 Table.
Type = WS.getTableType();
1698 assert(WasmIndices.count(&WS) == 0);
1699 WasmIndices[&WS] = Table.
Index;
1700 Tables.push_back(Table);
1703 << WasmIndices.find(&WS)->second <<
"\n");
1704 }
else if (WS.isTag()) {
1708 if (WS.isDefined()) {
1709 Index = NumTagImports + TagTypes.size();
1710 uint32_t SigIndex = getTagType(WS);
1711 assert(WasmIndices.count(&WS) == 0);
1712 WasmIndices[&WS] =
Index;
1713 TagTypes.push_back(SigIndex);
1716 assert(WasmIndices.count(&WS) > 0);
1718 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1731 if (!
S.isVariable())
1739 ": absolute addressing not supported!");
1747 if (
Base->isFunction()) {
1750 assert(WasmIndices.count(&WS) == 0);
1751 WasmIndices[&WS] = WasmIndex;
1753 }
else if (
Base->isData()) {
1754 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1761 if (!
Base->getSize()->evaluateAsAbsolute(Size, Layout))
1763 const WasmDataSegment &Segment =
1764 DataSegments[DataSection.getSegmentIndex()];
1768 DataSection.getSegmentIndex(),
1771 DataLocations[&WS] =
Ref;
1793 if (!WS.isExternal() && WS.isDefined())
1795 if (WS.isUndefined())
1797 if (WS.isNoStrip()) {
1799 if (isEmscripten()) {
1803 if (WS.hasImportName())
1805 if (WS.hasExportName())
1811 Info.Name = WS.getName();
1815 assert(WasmIndices.count(&WS) > 0);
1816 Info.ElementIndex = WasmIndices.find(&WS)->second;
1817 }
else if (WS.isDefined()) {
1818 assert(DataLocations.count(&WS) > 0);
1819 Info.DataRef = DataLocations.find(&WS)->second;
1821 WS.setIndex(SymbolInfos.size());
1826 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1830 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1831 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1832 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1833 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1834 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1835 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1837 assert(Rel.Symbol->isFunction());
1840 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1841 uint32_t TableIndex = TableElems.size() + InitialTableOffset;
1842 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1844 <<
" to table: " << TableIndex <<
"\n");
1845 TableElems.push_back(FunctionIndex);
1846 registerFunctionType(*
Base);
1850 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1851 HandleReloc(RelEntry);
1852 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1853 HandleReloc(RelEntry);
1859 if (WS.getName().startswith(
".fini_array"))
1861 if (!WS.getName().startswith(
".init_array"))
1863 if (WS.getFragmentList().empty())
1867 if (WS.getFragmentList().size() != 3)
1870 auto IT = WS.begin();
1887 unsigned PrefixLength = strlen(
".init_array");
1888 if (WS.getName().size() > PrefixLength) {
1889 if (WS.getName()[PrefixLength] !=
'.')
1891 ".init_array section priority should start with '.'");
1892 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1895 const auto &DataFrag = cast<MCDataFragment>(Frag);
1897 for (
const uint8_t *
1898 P = (
const uint8_t *)Contents.data(),
1899 *End = (
const uint8_t *)Contents.data() + Contents.size();
1904 for (
const MCFixup &Fixup : DataFrag.getFixups()) {
1908 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1911 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1914 if (!TargetSym.isFunction())
1916 InitFuncs.push_back(
1917 std::make_pair(Priority, TargetSym.getIndex()));
1924 uint32_t CodeSectionIndex, DataSectionIndex;
1925 if (
Mode != DwoMode::DwoOnly) {
1926 writeTypeSection(Signatures);
1927 writeImportSection(Imports, DataSize, TableElems.size());
1928 writeFunctionSection(Functions);
1929 writeTableSection(Tables);
1931 writeTagSection(TagTypes);
1932 writeGlobalSection(Globals);
1933 writeExportSection(Exports);
1934 const MCSymbol *IndirectFunctionTable =
1935 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1936 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1938 writeDataCountSection();
1940 CodeSectionIndex = writeCodeSection(
Asm, Layout, Functions);
1941 DataSectionIndex = writeDataSection(Layout);
1946 for (
auto &Group : Comdats) {
1947 for (
auto &Entry : Group.second) {
1949 Entry.Index += SectionCount;
1953 for (
auto &CustomSection : CustomSections)
1954 writeCustomSection(CustomSection,
Asm, Layout);
1956 if (
Mode != DwoMode::DwoOnly) {
1957 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1959 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1960 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1962 writeCustomRelocSections();
1963 if (ProducersSection)
1964 writeCustomSection(*ProducersSection,
Asm, Layout);
1965 if (TargetFeaturesSection)
1966 writeCustomSection(*TargetFeaturesSection,
Asm, Layout);
1969 return W->OS.tell() - StartOffset;
1972 std::unique_ptr<MCObjectWriter>
1975 return std::make_unique<WasmObjectWriter>(
std::move(MOTW), OS);
1978 std::unique_ptr<MCObjectWriter>
1982 return std::make_unique<WasmObjectWriter>(
std::move(MOTW), OS, DwoOS);