16#include "llvm/Config/llvm-config.h"
37#define DEBUG_TYPE "mc"
43static const uint32_t InitialTableOffset = 1;
48struct SectionBookkeeping {
62struct WasmDataSegment {
87struct WasmComdatEntry {
93struct WasmRelocationEntry {
101 int64_t Addend,
unsigned Type,
103 : Offset(Offset), Symbol(Symbol), Addend(Addend),
Type(
Type),
104 FixupSection(FixupSection) {}
110 <<
", Sym=" << *Symbol <<
", Addend=" << Addend
111 <<
", FixupSection=" << FixupSection->
getName();
114#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
121struct WasmCustomSection {
130 : Name(Name), Section(Section) {}
142template <
typename T,
int W>
152template <
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);
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);
369void 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++;
388void WasmObjectWriter::writeStringWithAlignment(
const StringRef Str,
389 unsigned Alignment) {
400 assert((StrSizeLength + Paddings) <= 5 &&
"too long string to align");
408void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
414 Section.PayloadOffset =
W->OS.tell();
417 if (
Name !=
"__clangast") {
421 writeStringWithAlignment(
Name, 4);
425 Section.ContentsOffset =
W->OS.tell();
430void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
450void WasmObjectWriter::writeHeader(
const MCAssembler &Asm) {
455void WasmObjectWriter::executePostLayoutBinding(
MCAssembler &Asm,
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));
483void WasmObjectWriter::recordRelocation(
MCAssembler &Asm,
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);
644WasmObjectWriter::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)
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);
754WasmObjectWriter::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();
767void 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:
824void WasmObjectWriter::writeTypeSection(
860 writeString(
Import.Module);
861 writeString(
Import.Field);
894 if (Functions.
empty())
901 for (
const WasmFunction &Func : Functions)
908 if (TagTypes.
empty())
934 if (
Global.InitExpr.Extended) {
938 switch (
Global.Type.Type) {
952 writeValueType(wasm::ValType::EXTERNREF);
999void 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);
1039void 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);
1107void 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);
1147void WasmObjectWriter::writeCustomRelocSections() {
1148 for (
const auto &Sec : CustomSections) {
1149 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1150 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1154void 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);
1239void 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];
1271void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1276 if (
auto *Sig =
Symbol.getSignature()) {
1284 TypeIndices[&
Symbol] = Pair.first->second;
1287 <<
" new:" << Pair.second <<
"\n");
1288 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1291void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1297 if (
auto *Sig =
Symbol.getSignature()) {
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");
1331void WasmObjectWriter::prepareImports(
1338 MemImport.
Module =
"env";
1339 MemImport.
Field =
"__linear_memory";
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);
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();
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);
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();
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();
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;
1602 Comdats[
C->getName()].emplace_back(
1606 if (WS.hasExportName()) {
1608 Export.Name = WS.getExportName();
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();
1658 Global.InitExpr.Extended =
false;
1659 switch (
Global.Type.Type) {
1678 assert(WasmIndices.count(&WS) == 0);
1679 WasmIndices[&WS] =
Global.Index;
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;
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;
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!");
1740 if (
Base->isFunction()) {
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");
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();
1902 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1905 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1908 if (!TargetSym.isFunction())
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);
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;
1966std::unique_ptr<MCObjectWriter>
1969 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS);
1972std::unique_ptr<MCObjectWriter>
1976 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS, DwoOS);
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 void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const FuncProtoTy Signatures[]
static const unsigned InvalidIndex
static void addData(SmallVectorImpl< char > &DataBytes, MCSectionWasm &DataSection)
static bool isInSymtab(const MCSymbolWasm &Sym)
static uint32_t getAlignment(const MCSectionCOFF &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.
Encapsulates the layout of an assembly file at a particular point in time.
const MCSymbol * getBaseSymbol(const MCSymbol &Symbol) const
If this symbol is equivalent to A + Constant, return A.
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
Get the offset of the given symbol, as computed in the current layout.
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
Context object for machine code objects.
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
void reportError(SMLoc L, const Twine &Msg)
Base class for the full range of assembler expressions which are needed for parsing.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
static MCFixupKind getKindForSize(unsigned Size, bool IsPCRel)
Return the generic fixup kind for a value with the given size.
FragmentType getKind() const
MCSection * getParent() const
bool hasInstructions() const
Does this fragment have instructions emitted into it? By default this is false, but specific fragment...
Defines the object file and target independent interfaces used by the assembler backend to write nati...
virtual uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout)=0
Write the object file and returns the number of bytes written.
virtual void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout)=0
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
virtual void reset()
lifetime management
virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue)=0
Record a relocation entry.
This represents a section on wasm.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
SectionKind getKind() const
StringRef getName() const
MCSymbol * getBeginSymbol()
Represent a reference to a symbol from inside an expression.
const MCSymbol & getSymbol() const
VariantKind getKind() const
bool isFunctionTable() const
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).
void setIndex(uint32_t Value) const
Set the (implementation defined) index.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
uint64_t Offset
The offset to apply to the fragment address to form this symbol's value.
bool isUsedInReloc() const
unsigned Kind
LLVM RTTI discriminator.
This represents an "assembler immediate".
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)
pointer data()
Return a pointer to the vector's buffer, even if empty().
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 endswith(StringRef Suffix) const
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
A raw_ostream that discards all output.
This class implements an extremely fast bulk output stream that can only output to a stream.
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.
@ C
The default llvm calling convention, compatible with C.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
void write64le(void *P, uint64_t V)
void write32le(void *P, uint32_t V)
const unsigned WASM_SYMBOL_UNDEFINED
const uint32_t WasmPageSize
const unsigned WASM_SYMBOL_NO_STRIP
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_LIMITS_FLAG_HAS_MAX
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
const unsigned WASM_SYMBOL_TLS
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
const uint32_t WasmMetadataVersion
const unsigned WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_LOCAL
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
const uint32_t WasmVersion
const unsigned WASM_SYMBOL_EXPORTED
bool relocTypeHasAddend(uint32_t type)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN
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)
void stable_sort(R &&Range)
@ Export
Export information to summary.
@ Import
Import information from summary.
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
std::unique_ptr< MCObjectWriter > createWasmObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Construct a new Wasm writer instance.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
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...
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.
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)
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)
This struct is a compact representation of a valid (non-zero power of two) alignment.
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
Adapter to write values to a stream in a particular byte order.
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params