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 {
130 : Name(Name), Section(Section) {}
142 template <
typename T,
int W>
152 template <
typename T,
int W>
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);
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");
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:
788 case wasm::R_WASM_MEMORY_ADDR_LEB64:
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:
799 case wasm::R_WASM_TABLE_INDEX_I64:
800 case wasm::R_WASM_MEMORY_ADDR_I64:
801 case wasm::R_WASM_FUNCTION_OFFSET_I64:
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:
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:
824 void WasmObjectWriter::writeTypeSection(
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) {
1065 FuncSection->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1066 Asm.writeSectionData(
W->OS, FuncSection, Layout);
1070 applyRelocations(CodeRelocations,
Section.ContentsOffset, Layout);
1072 endSection(Section);
1077 if (DataSegments.empty())
1085 for (
const WasmDataSegment &Segment : DataSegments) {
1096 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1097 W->OS << Segment.Data;
1101 applyRelocations(DataRelocations,
Section.ContentsOffset, Layout);
1103 endSection(Section);
1107 void WasmObjectWriter::writeRelocSection(
1109 std::vector<WasmRelocationEntry> &Relocs) {
1122 Relocs, [](
const WasmRelocationEntry &A,
const WasmRelocationEntry &
B) {
1123 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1124 (
B.Offset +
B.FixupSection->getSectionOffset());
1128 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1132 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1134 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1137 W->OS << char(RelEntry.Type);
1140 if (RelEntry.hasAddend())
1144 endSection(Section);
1147 void WasmObjectWriter::writeCustomRelocSections() {
1148 for (
const auto &Sec : CustomSections) {
1149 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1150 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1154 void WasmObjectWriter::writeLinkingMetaDataSection(
1156 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1157 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1159 startCustomSection(Section,
"linking");
1162 SectionBookkeeping SubSection;
1163 if (SymbolInfos.
size() != 0) {
1177 writeString(Sym.Name);
1180 writeString(Sym.Name);
1189 CustomSections[Sym.ElementIndex].OutputIndex;
1197 endSection(SubSection);
1200 if (DataSegments.size()) {
1203 for (
const WasmDataSegment &Segment : DataSegments) {
1204 writeString(Segment.Name);
1208 endSection(SubSection);
1211 if (!InitFuncs.empty()) {
1214 for (
auto &StartFunc : InitFuncs) {
1218 endSection(SubSection);
1221 if (Comdats.size()) {
1224 for (
const auto &
C : Comdats) {
1225 writeString(
C.first);
1228 for (
const WasmComdatEntry &Entry :
C.second) {
1233 endSection(SubSection);
1236 endSection(Section);
1239 void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1243 auto *Sec = CustomSection.Section;
1244 startCustomSection(Section, CustomSection.Name);
1246 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1247 Asm.writeSectionData(
W->OS, Sec, Layout);
1249 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1250 CustomSection.OutputIndex =
Section.Index;
1252 endSection(Section);
1255 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1256 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
1261 assert(TypeIndices.count(&Symbol));
1262 return TypeIndices[&
Symbol];
1267 assert(TypeIndices.count(&Symbol));
1268 return TypeIndices[&
Symbol];
1271 void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1276 if (
auto *Sig =
Symbol.getSignature()) {
1277 S.Returns = Sig->Returns;
1278 S.Params = Sig->Params;
1281 auto Pair = SignatureIndices.insert(std::make_pair(
S,
Signatures.size()));
1284 TypeIndices[&
Symbol] = Pair.first->second;
1287 <<
" new:" << Pair.second <<
"\n");
1288 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1291 void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1297 if (
auto *Sig =
Symbol.getSignature()) {
1298 S.Returns = Sig->Returns;
1299 S.Params = Sig->Params;
1302 auto Pair = SignatureIndices.insert(std::make_pair(
S,
Signatures.size()));
1305 TypeIndices[&
Symbol] = Pair.first->second;
1307 LLVM_DEBUG(
dbgs() <<
"registerTagType: " << Symbol <<
" new:" << Pair.second
1309 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1331 void WasmObjectWriter::prepareImports(
1338 MemImport.
Module =
"env";
1339 MemImport.
Field =
"__linear_memory";
1343 Imports.push_back(MemImport);
1353 if (WS.isFunction()) {
1357 ": absolute addressing not supported!");
1358 registerFunctionType(*cast<MCSymbolWasm>(BS));
1362 registerTagType(WS);
1364 if (WS.isTemporary())
1368 if (!WS.isDefined() && !WS.isComdat()) {
1369 if (WS.isFunction()) {
1371 Import.Module = WS.getImportModule();
1372 Import.Field = WS.getImportName();
1374 Import.SigIndex = getFunctionType(WS);
1375 Imports.push_back(Import);
1376 assert(WasmIndices.count(&WS) == 0);
1377 WasmIndices[&WS] = NumFunctionImports++;
1378 }
else if (WS.isGlobal()) {
1383 Import.Field = WS.getImportName();
1385 Import.Module = WS.getImportModule();
1386 Import.Global = WS.getGlobalType();
1387 Imports.push_back(Import);
1388 assert(WasmIndices.count(&WS) == 0);
1389 WasmIndices[&WS] = NumGlobalImports++;
1390 }
else if (WS.isTag()) {
1395 Import.Module = WS.getImportModule();
1396 Import.Field = WS.getImportName();
1398 Import.SigIndex = getTagType(WS);
1399 Imports.push_back(Import);
1400 assert(WasmIndices.count(&WS) == 0);
1401 WasmIndices[&WS] = NumTagImports++;
1402 }
else if (WS.isTable()) {
1407 Import.Module = WS.getImportModule();
1408 Import.Field = WS.getImportName();
1410 Import.Table = WS.getTableType();
1411 Imports.push_back(Import);
1412 assert(WasmIndices.count(&WS) == 0);
1413 WasmIndices[&WS] = NumTableImports++;
1421 if (WS.isUsedInGOT()) {
1423 if (WS.isFunction())
1424 Import.Module =
"GOT.func";
1426 Import.Module =
"GOT.mem";
1427 Import.Field = WS.getName();
1430 Imports.push_back(Import);
1431 assert(GOTIndices.count(&WS) == 0);
1432 GOTIndices[&WS] = NumGlobalImports++;
1442 uint64_t TotalSize = writeOneObject(
Asm, Layout, DwoMode::NonDwoOnly);
1446 return TotalSize + writeOneObject(
Asm, Layout, DwoMode::DwoOnly);
1448 return writeOneObject(
Asm, Layout, DwoMode::AllSections);
1457 CustomSections.clear();
1471 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1473 if (
Mode != DwoMode::DwoOnly) {
1474 prepareImports(Imports,
Asm, Layout);
1483 if (
Mode == DwoMode::NonDwoOnly && isDwoSection(Sec))
1485 if (
Mode == DwoMode::DwoOnly && !isDwoSection(Sec))
1489 <<
Section.getGroup() <<
"\n";);
1496 if (
Section.getKind().isText())
1500 uint32_t SegmentIndex = DataSegments.size();
1502 DataSegments.emplace_back();
1503 WasmDataSegment &Segment = DataSegments.back();
1505 Segment.InitFlags =
Section.getPassive()
1508 Segment.Offset = DataSize;
1510 addData(Segment.Data, Section);
1512 Segment.LinkingFlags =
Section.getSegmentFlags();
1513 DataSize += Segment.Data.size();
1514 Section.setSegmentIndex(SegmentIndex);
1517 Comdats[
C->getName()].emplace_back(
1522 assert(Sec.getKind().isMetadata());
1527 if (
Name.startswith(
".custom_section."))
1528 Name =
Name.substr(strlen(
".custom_section."));
1530 MCSymbol *Begin = Sec.getBeginSymbol();
1532 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1533 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1537 if (Name ==
"producers") {
1538 ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section);
1541 if (Name ==
"target_features") {
1542 TargetFeaturesSection =
1543 std::make_unique<WasmCustomSection>(Name, &Section);
1552 Comdats[
C->getName()].emplace_back(
1554 static_cast<uint32_t>(CustomSections.size())});
1557 CustomSections.emplace_back(Name, &Section);
1561 if (
Mode != DwoMode::DwoOnly) {
1566 if (
S.isTemporary() &&
S.getName().empty())
1571 dbgs() <<
"MCSymbol: "
1574 <<
" isDefined=" <<
S.isDefined() <<
" isExternal="
1575 <<
S.isExternal() <<
" isTemporary=" <<
S.isTemporary()
1576 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1577 <<
" isVariable=" << WS.isVariable() <<
"\n");
1579 if (WS.isVariable())
1581 if (WS.isComdat() && !WS.isDefined())
1584 if (WS.isFunction()) {
1586 if (WS.isDefined()) {
1587 if (WS.getOffset() != 0)
1589 "function sections must contain one function each");
1592 Index = NumFunctionImports + Functions.size();
1594 Func.SigIndex = getFunctionType(WS);
1595 Func.Section = &WS.getSection();
1596 assert(WasmIndices.count(&WS) == 0);
1597 WasmIndices[&WS] =
Index;
1598 Functions.push_back(Func);
1602 Comdats[
C->getName()].emplace_back(
1606 if (WS.hasExportName()) {
1608 Export.Name = WS.getExportName();
1611 Exports.push_back(Export);
1615 Index = WasmIndices.find(&WS)->second;
1620 }
else if (WS.isData()) {
1624 if (!WS.isDefined()) {
1635 if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
1638 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1639 if (!DataSection.isWasmData())
1648 assert(DataLocations.count(&WS) == 0);
1649 DataLocations[&WS] =
Ref;
1652 }
else if (WS.isGlobal()) {
1654 if (WS.isDefined()) {
1656 Global.Type = WS.getGlobalType();
1657 Global.Index = NumGlobalImports + Globals.size();
1658 Global.InitExpr.Extended =
false;
1659 switch (
Global.Type.Type) {
1678 assert(WasmIndices.count(&WS) == 0);
1679 WasmIndices[&WS] =
Global.Index;
1680 Globals.push_back(Global);
1684 << WasmIndices.find(&WS)->second <<
"\n");
1686 }
else if (WS.isTable()) {
1687 if (WS.isDefined()) {
1689 Table.
Index = NumTableImports + Tables.size();
1690 Table.
Type = WS.getTableType();
1691 assert(WasmIndices.count(&WS) == 0);
1692 WasmIndices[&WS] = Table.
Index;
1693 Tables.push_back(Table);
1696 << WasmIndices.find(&WS)->second <<
"\n");
1697 }
else if (WS.isTag()) {
1701 if (WS.isDefined()) {
1702 Index = NumTagImports + TagTypes.size();
1703 uint32_t SigIndex = getTagType(WS);
1704 assert(WasmIndices.count(&WS) == 0);
1705 WasmIndices[&WS] =
Index;
1706 TagTypes.push_back(SigIndex);
1709 assert(WasmIndices.count(&WS) > 0);
1711 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1724 if (!
S.isVariable())
1732 ": absolute addressing not supported!");
1737 LLVM_DEBUG(
dbgs() << WS.getName() <<
": weak alias of '" << *Base
1740 if (
Base->isFunction()) {
1741 assert(WasmIndices.count(Base) > 0);
1742 uint32_t WasmIndex = WasmIndices.find(Base)->second;
1743 assert(WasmIndices.count(&WS) == 0);
1744 WasmIndices[&WS] = WasmIndex;
1746 }
else if (
Base->isData()) {
1747 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1754 if (!
Base->getSize()->evaluateAsAbsolute(Size, Layout))
1756 const WasmDataSegment &Segment =
1757 DataSegments[DataSection.getSegmentIndex()];
1761 DataSection.getSegmentIndex(),
1764 DataLocations[&WS] =
Ref;
1786 if (!WS.isExternal() && WS.isDefined())
1788 if (WS.isUndefined())
1790 if (WS.isNoStrip()) {
1792 if (isEmscripten()) {
1796 if (WS.hasImportName())
1798 if (WS.hasExportName())
1804 Info.Name = WS.getName();
1808 assert(WasmIndices.count(&WS) > 0);
1809 Info.ElementIndex = WasmIndices.find(&WS)->second;
1810 }
else if (WS.isDefined()) {
1811 assert(DataLocations.count(&WS) > 0);
1812 Info.DataRef = DataLocations.find(&WS)->second;
1814 WS.setIndex(SymbolInfos.size());
1819 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1823 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1824 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1825 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1826 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1827 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1828 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1830 assert(Rel.Symbol->isFunction());
1833 uint32_t FunctionIndex = WasmIndices.find(Base)->second;
1834 uint32_t TableIndex = TableElems.size() + InitialTableOffset;
1835 if (TableIndices.try_emplace(Base, TableIndex).second) {
1837 <<
" to table: " << TableIndex <<
"\n");
1838 TableElems.push_back(FunctionIndex);
1839 registerFunctionType(*Base);
1843 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1844 HandleReloc(RelEntry);
1845 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1846 HandleReloc(RelEntry);
1852 if (WS.getName().startswith(
".fini_array"))
1854 if (!WS.getName().startswith(
".init_array"))
1856 if (WS.getFragmentList().empty())
1860 if (WS.getFragmentList().size() != 3)
1863 auto IT = WS.begin();
1881 unsigned PrefixLength = strlen(
".init_array");
1882 if (WS.getName().size() > PrefixLength) {
1883 if (WS.getName()[PrefixLength] !=
'.')
1885 ".init_array section priority should start with '.'");
1886 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1889 const auto &DataFrag = cast<MCDataFragment>(Frag);
1891 for (
const uint8_t *
1892 P = (
const uint8_t *)Contents.data(),
1893 *End = (
const uint8_t *)Contents.data() + Contents.size();
1898 for (
const MCFixup &Fixup : DataFrag.getFixups()) {
1902 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1905 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1908 if (!TargetSym.isFunction())
1910 InitFuncs.push_back(
1911 std::make_pair(Priority, TargetSym.getIndex()));
1918 uint32_t CodeSectionIndex, DataSectionIndex;
1919 if (
Mode != DwoMode::DwoOnly) {
1921 writeImportSection(Imports, DataSize, TableElems.size());
1922 writeFunctionSection(Functions);
1923 writeTableSection(Tables);
1925 writeTagSection(TagTypes);
1926 writeGlobalSection(Globals);
1927 writeExportSection(Exports);
1928 const MCSymbol *IndirectFunctionTable =
1929 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1930 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1932 writeDataCountSection();
1934 CodeSectionIndex = writeCodeSection(
Asm, Layout, Functions);
1935 DataSectionIndex = writeDataSection(Layout);
1940 for (
auto &Group : Comdats) {
1941 for (
auto &Entry : Group.second) {
1943 Entry.Index += SectionCount;
1947 for (
auto &CustomSection : CustomSections)
1948 writeCustomSection(CustomSection,
Asm, Layout);
1950 if (
Mode != DwoMode::DwoOnly) {
1951 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1953 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1954 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1956 writeCustomRelocSections();
1957 if (ProducersSection)
1958 writeCustomSection(*ProducersSection,
Asm, Layout);
1959 if (TargetFeaturesSection)
1960 writeCustomSection(*TargetFeaturesSection,
Asm, Layout);
1963 return W->OS.tell() - StartOffset;
1966 std::unique_ptr<MCObjectWriter>
1969 return std::make_unique<WasmObjectWriter>(
std::move(MOTW), OS);
1972 std::unique_ptr<MCObjectWriter>
1976 return std::make_unique<WasmObjectWriter>(
std::move(MOTW), OS, DwoOS);