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")) {
465 if (WasmSym->isNoStrip())
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.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().starts_with(
".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.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";
598 if (!
Sym->isFunctionTable())
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.isText()) {
631 CodeRelocations.push_back(Rec);
632 }
else if (FixupSection.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_FUNCTION_INDEX_I32:
675 case wasm::R_WASM_GLOBAL_INDEX_LEB:
676 case wasm::R_WASM_GLOBAL_INDEX_I32:
677 case wasm::R_WASM_TAG_INDEX_LEB:
678 case wasm::R_WASM_TABLE_NUMBER_LEB:
680 assert(WasmIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in wasm index space");
681 return WasmIndices[RelEntry.Symbol];
682 case wasm::R_WASM_FUNCTION_OFFSET_I32:
683 case wasm::R_WASM_FUNCTION_OFFSET_I64:
684 case wasm::R_WASM_SECTION_OFFSET_I32: {
685 if (!RelEntry.Symbol->isDefined())
688 static_cast<const MCSectionWasm &
>(RelEntry.Symbol->getSection());
689 return Section.getSectionOffset() + RelEntry.Addend;
691 case wasm::R_WASM_MEMORY_ADDR_LEB:
692 case wasm::R_WASM_MEMORY_ADDR_LEB64:
693 case wasm::R_WASM_MEMORY_ADDR_SLEB:
694 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
695 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
696 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
697 case wasm::R_WASM_MEMORY_ADDR_I32:
698 case wasm::R_WASM_MEMORY_ADDR_I64:
699 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
700 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
701 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {
704 if (!RelEntry.Symbol->isDefined())
707 const WasmDataSegment &Segment = DataSegments[SymRef.
Segment];
709 return Segment.Offset + SymRef.
Offset + RelEntry.Addend;
723 if (Frag.hasInstructions())
726 if (
auto *
Align = dyn_cast<MCAlignFragment>(&Frag)) {
727 if (
Align->getValueSize() != 1)
733 DataBytes.
size() +
Align->getMaxBytesToEmit());
735 }
else if (
auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
737 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
739 DataBytes.
insert(DataBytes.
end(), Fill->getValueSize() * NumValues,
741 }
else if (
auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
745 const auto &DataFrag = cast<MCDataFragment>(Frag);
755WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
756 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
757 if (!TypeIndices.count(RelEntry.Symbol))
759 RelEntry.Symbol->getName());
760 return TypeIndices[RelEntry.Symbol];
763 return RelEntry.Symbol->getIndex();
768void WasmObjectWriter::applyRelocations(
772 for (
const WasmRelocationEntry &RelEntry : Relocations) {
774 RelEntry.FixupSection->getSectionOffset() +
780 switch (RelEntry.Type) {
781 case wasm::R_WASM_FUNCTION_INDEX_LEB:
782 case wasm::R_WASM_TYPE_INDEX_LEB:
783 case wasm::R_WASM_GLOBAL_INDEX_LEB:
784 case wasm::R_WASM_MEMORY_ADDR_LEB:
785 case wasm::R_WASM_TAG_INDEX_LEB:
786 case wasm::R_WASM_TABLE_NUMBER_LEB:
789 case wasm::R_WASM_MEMORY_ADDR_LEB64:
792 case wasm::R_WASM_TABLE_INDEX_I32:
793 case wasm::R_WASM_MEMORY_ADDR_I32:
794 case wasm::R_WASM_FUNCTION_OFFSET_I32:
795 case wasm::R_WASM_FUNCTION_INDEX_I32:
796 case wasm::R_WASM_SECTION_OFFSET_I32:
797 case wasm::R_WASM_GLOBAL_INDEX_I32:
798 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
801 case wasm::R_WASM_TABLE_INDEX_I64:
802 case wasm::R_WASM_MEMORY_ADDR_I64:
803 case wasm::R_WASM_FUNCTION_OFFSET_I64:
806 case wasm::R_WASM_TABLE_INDEX_SLEB:
807 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
808 case wasm::R_WASM_MEMORY_ADDR_SLEB:
809 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
810 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
813 case wasm::R_WASM_TABLE_INDEX_SLEB64:
814 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
815 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
816 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
817 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
826void WasmObjectWriter::writeTypeSection(
862 writeString(
Import.Module);
863 writeString(
Import.Field);
896 if (Functions.
empty())
903 for (
const WasmFunction &Func : Functions)
910 if (TagTypes.
empty())
936 if (
Global.InitExpr.Extended) {
940 switch (
Global.Type.Type) {
954 writeValueType(wasm::ValType::EXTERNREF);
975 assert(Table.Type.ElemType != wasm::ValType::OTHERREF &&
976 "Cannot encode general ref-typed tables");
1000 endSection(Section);
1003void WasmObjectWriter::writeElemSection(
1005 if (TableElems.
empty())
1008 assert(IndirectFunctionTable);
1015 assert(WasmIndices.count(IndirectFunctionTable));
1016 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
1033 const uint8_t ElemKind = 0;
1041 endSection(Section);
1044void WasmObjectWriter::writeDataCountSection() {
1045 if (DataSegments.empty())
1051 endSection(Section);
1057 if (Functions.
empty())
1065 for (
const WasmFunction &Func : Functions) {
1070 FuncSection->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1071 Asm.writeSectionData(
W->OS, FuncSection, Layout);
1075 applyRelocations(CodeRelocations,
Section.ContentsOffset, Layout);
1077 endSection(Section);
1082 if (DataSegments.empty())
1090 for (
const WasmDataSegment &Segment : DataSegments) {
1101 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1102 W->OS << Segment.Data;
1106 applyRelocations(DataRelocations,
Section.ContentsOffset, Layout);
1108 endSection(Section);
1112void WasmObjectWriter::writeRelocSection(
1114 std::vector<WasmRelocationEntry> &Relocs) {
1127 Relocs, [](
const WasmRelocationEntry &
A,
const WasmRelocationEntry &
B) {
1128 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1129 (
B.Offset +
B.FixupSection->getSectionOffset());
1133 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1137 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1139 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1142 W->OS <<
char(RelEntry.Type);
1145 if (RelEntry.hasAddend())
1149 endSection(Section);
1152void WasmObjectWriter::writeCustomRelocSections() {
1153 for (
const auto &Sec : CustomSections) {
1154 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1155 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1159void WasmObjectWriter::writeLinkingMetaDataSection(
1161 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1162 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1164 startCustomSection(Section,
"linking");
1167 SectionBookkeeping SubSection;
1168 if (SymbolInfos.
size() != 0) {
1182 writeString(
Sym.Name);
1185 writeString(
Sym.Name);
1194 CustomSections[
Sym.ElementIndex].OutputIndex;
1202 endSection(SubSection);
1205 if (DataSegments.size()) {
1208 for (
const WasmDataSegment &Segment : DataSegments) {
1209 writeString(Segment.Name);
1213 endSection(SubSection);
1216 if (!InitFuncs.empty()) {
1219 for (
auto &StartFunc : InitFuncs) {
1223 endSection(SubSection);
1226 if (Comdats.size()) {
1229 for (
const auto &
C : Comdats) {
1230 writeString(
C.first);
1233 for (
const WasmComdatEntry &Entry :
C.second) {
1238 endSection(SubSection);
1241 endSection(Section);
1244void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1248 auto *Sec = CustomSection.Section;
1249 startCustomSection(Section, CustomSection.Name);
1251 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1252 Asm.writeSectionData(
W->OS, Sec, Layout);
1254 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1255 CustomSection.OutputIndex =
Section.Index;
1257 endSection(Section);
1260 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1261 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
1266 assert(TypeIndices.count(&Symbol));
1267 return TypeIndices[&
Symbol];
1272 assert(TypeIndices.count(&Symbol));
1273 return TypeIndices[&
Symbol];
1276void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1281 if (
auto *Sig =
Symbol.getSignature()) {
1289 TypeIndices[&
Symbol] = Pair.first->second;
1292 <<
" new:" << Pair.second <<
"\n");
1293 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1296void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1302 if (
auto *Sig =
Symbol.getSignature()) {
1310 TypeIndices[&
Symbol] = Pair.first->second;
1312 LLVM_DEBUG(
dbgs() <<
"registerTagType: " << Symbol <<
" new:" << Pair.second
1314 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1318 if (
Sym.isUsedInReloc() ||
Sym.isUsedInInitArray())
1321 if (
Sym.isComdat() && !
Sym.isDefined())
1324 if (
Sym.isTemporary())
1327 if (
Sym.isSection())
1330 if (
Sym.omitFromLinkingSection())
1336void WasmObjectWriter::prepareImports(
1343 MemImport.
Module =
"env";
1344 MemImport.
Field =
"__linear_memory";
1358 if (WS.isFunction()) {
1362 ": absolute addressing not supported!");
1363 registerFunctionType(*cast<MCSymbolWasm>(BS));
1367 registerTagType(WS);
1369 if (WS.isTemporary())
1373 if (!WS.isDefined() && !WS.isComdat()) {
1374 if (WS.isFunction()) {
1376 Import.Module = WS.getImportModule();
1377 Import.Field = WS.getImportName();
1379 Import.SigIndex = getFunctionType(WS);
1381 assert(WasmIndices.count(&WS) == 0);
1382 WasmIndices[&WS] = NumFunctionImports++;
1383 }
else if (WS.isGlobal()) {
1388 Import.Field = WS.getImportName();
1390 Import.Module = WS.getImportModule();
1391 Import.Global = WS.getGlobalType();
1393 assert(WasmIndices.count(&WS) == 0);
1394 WasmIndices[&WS] = NumGlobalImports++;
1395 }
else if (WS.isTag()) {
1400 Import.Module = WS.getImportModule();
1401 Import.Field = WS.getImportName();
1403 Import.SigIndex = getTagType(WS);
1405 assert(WasmIndices.count(&WS) == 0);
1406 WasmIndices[&WS] = NumTagImports++;
1407 }
else if (WS.isTable()) {
1412 Import.Module = WS.getImportModule();
1413 Import.Field = WS.getImportName();
1415 Import.Table = WS.getTableType();
1417 assert(WasmIndices.count(&WS) == 0);
1418 WasmIndices[&WS] = NumTableImports++;
1426 if (WS.isUsedInGOT()) {
1428 if (WS.isFunction())
1429 Import.Module =
"GOT.func";
1431 Import.Module =
"GOT.mem";
1432 Import.Field = WS.getName();
1436 assert(GOTIndices.count(&WS) == 0);
1437 GOTIndices[&WS] = NumGlobalImports++;
1447 uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly);
1451 return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly);
1453 return writeOneObject(Asm, Layout, DwoMode::AllSections);
1462 CustomSections.clear();
1476 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1478 if (Mode != DwoMode::DwoOnly) {
1479 prepareImports(Imports, Asm, Layout);
1494 <<
Section.getGroup() <<
"\n";);
1505 uint32_t SegmentIndex = DataSegments.size();
1507 DataSegments.emplace_back();
1508 WasmDataSegment &Segment = DataSegments.back();
1510 Segment.InitFlags =
Section.getPassive()
1513 Segment.Offset = DataSize;
1515 addData(Segment.Data, Section);
1517 Segment.LinkingFlags =
Section.getSegmentFlags();
1518 DataSize += Segment.Data.size();
1519 Section.setSegmentIndex(SegmentIndex);
1522 Comdats[
C->getName()].emplace_back(
1532 Name.consume_front(
".custom_section.");
1534 MCSymbol *Begin = Sec.getBeginSymbol();
1536 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1537 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1541 if (
Name ==
"producers") {
1542 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &Section);
1545 if (
Name ==
"target_features") {
1546 TargetFeaturesSection =
1547 std::make_unique<WasmCustomSection>(
Name, &Section);
1556 Comdats[
C->getName()].emplace_back(
1558 static_cast<uint32_t>(CustomSections.size())});
1561 CustomSections.emplace_back(
Name, &Section);
1565 if (Mode != DwoMode::DwoOnly) {
1570 if (S.isTemporary() && S.getName().empty())
1575 dbgs() <<
"MCSymbol: "
1578 <<
" isDefined=" << S.isDefined() <<
" isExternal="
1579 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1580 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1581 <<
" isVariable=" << WS.isVariable() <<
"\n");
1583 if (WS.isVariable())
1585 if (WS.isComdat() && !WS.isDefined())
1588 if (WS.isFunction()) {
1590 if (WS.isDefined()) {
1591 if (WS.getOffset() != 0)
1593 "function sections must contain one function each");
1596 Index = NumFunctionImports + Functions.
size();
1598 Func.SigIndex = getFunctionType(WS);
1599 Func.Section = &WS.getSection();
1600 assert(WasmIndices.count(&WS) == 0);
1601 WasmIndices[&WS] =
Index;
1606 Comdats[
C->getName()].emplace_back(
1610 if (WS.hasExportName()) {
1612 Export.Name = WS.getExportName();
1619 Index = WasmIndices.find(&WS)->second;
1624 }
else if (WS.isData()) {
1628 if (!WS.isDefined()) {
1639 if (!WS.getSize()->evaluateAsAbsolute(
Size, Layout))
1642 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1643 if (!DataSection.isWasmData())
1652 assert(DataLocations.count(&WS) == 0);
1653 DataLocations[&WS] =
Ref;
1656 }
else if (WS.isGlobal()) {
1658 if (WS.isDefined()) {
1660 Global.Type = WS.getGlobalType();
1661 Global.Index = NumGlobalImports + Globals.
size();
1662 Global.InitExpr.Extended =
false;
1663 switch (
Global.Type.Type) {
1682 assert(WasmIndices.count(&WS) == 0);
1683 WasmIndices[&WS] =
Global.Index;
1688 << WasmIndices.find(&WS)->second <<
"\n");
1690 }
else if (WS.isTable()) {
1691 if (WS.isDefined()) {
1693 Table.
Index = NumTableImports + Tables.
size();
1694 Table.
Type = WS.getTableType();
1695 assert(WasmIndices.count(&WS) == 0);
1696 WasmIndices[&WS] = Table.
Index;
1700 << WasmIndices.find(&WS)->second <<
"\n");
1701 }
else if (WS.isTag()) {
1705 if (WS.isDefined()) {
1706 Index = NumTagImports + TagTypes.
size();
1707 uint32_t SigIndex = getTagType(WS);
1708 assert(WasmIndices.count(&WS) == 0);
1709 WasmIndices[&WS] =
Index;
1713 assert(WasmIndices.count(&WS) > 0);
1715 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1728 if (!S.isVariable())
1736 ": absolute addressing not supported!");
1744 if (
Base->isFunction()) {
1747 assert(WasmIndices.count(&WS) == 0);
1748 WasmIndices[&WS] = WasmIndex;
1750 }
else if (
Base->isData()) {
1751 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1758 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Layout))
1760 const WasmDataSegment &Segment =
1761 DataSegments[DataSection.getSegmentIndex()];
1765 DataSection.getSegmentIndex(),
1768 DataLocations[&WS] =
Ref;
1790 if (!WS.isExternal() && WS.isDefined())
1792 if (WS.isUndefined())
1794 if (WS.isNoStrip()) {
1796 if (isEmscripten()) {
1800 if (WS.hasImportName())
1802 if (WS.hasExportName())
1808 Info.Name = WS.getName();
1812 assert(WasmIndices.count(&WS) > 0);
1813 Info.ElementIndex = WasmIndices.find(&WS)->second;
1814 }
else if (WS.isDefined()) {
1815 assert(DataLocations.count(&WS) > 0);
1816 Info.DataRef = DataLocations.find(&WS)->second;
1818 WS.setIndex(SymbolInfos.
size());
1823 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1827 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1828 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1829 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1830 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1831 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1832 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1834 assert(Rel.Symbol->isFunction());
1837 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1838 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1839 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1841 <<
" to table: " << TableIndex <<
"\n");
1843 registerFunctionType(*
Base);
1847 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1848 HandleReloc(RelEntry);
1849 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1850 HandleReloc(RelEntry);
1856 if (WS.getName().starts_with(
".fini_array"))
1858 if (!WS.getName().starts_with(
".init_array"))
1860 auto IT = WS.begin();
1870 if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
1879 unsigned PrefixLength = strlen(
".init_array");
1880 if (WS.getName().size() > PrefixLength) {
1881 if (WS.getName()[PrefixLength] !=
'.')
1883 ".init_array section priority should start with '.'");
1884 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1887 const auto &DataFrag = cast<MCDataFragment>(Frag);
1889 for (
const uint8_t *
1890 P = (
const uint8_t *)Contents.
data(),
1891 *
End = (
const uint8_t *)Contents.
data() + Contents.
size();
1900 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1903 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1906 if (!TargetSym.isFunction())
1909 std::make_pair(Priority, TargetSym.getIndex()));
1916 uint32_t CodeSectionIndex, DataSectionIndex;
1917 if (Mode != DwoMode::DwoOnly) {
1919 writeImportSection(Imports, DataSize, TableElems.
size());
1920 writeFunctionSection(Functions);
1921 writeTableSection(Tables);
1923 writeTagSection(TagTypes);
1924 writeGlobalSection(Globals);
1925 writeExportSection(Exports);
1926 const MCSymbol *IndirectFunctionTable =
1927 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1928 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1930 writeDataCountSection();
1932 CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
1933 DataSectionIndex = writeDataSection(Layout);
1938 for (
auto &Group : Comdats) {
1939 for (
auto &Entry : Group.second) {
1941 Entry.Index += SectionCount;
1945 for (
auto &CustomSection : CustomSections)
1946 writeCustomSection(CustomSection, Asm, Layout);
1948 if (Mode != DwoMode::DwoOnly) {
1949 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1951 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1952 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1954 writeCustomRelocSections();
1955 if (ProducersSection)
1956 writeCustomSection(*ProducersSection, Asm, Layout);
1957 if (TargetFeaturesSection)
1958 writeCustomSection(*TargetFeaturesSection, Asm, Layout);
1961 return W->OS.tell() - StartOffset;
1964std::unique_ptr<MCObjectWriter>
1967 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS);
1970std::unique_ptr<MCObjectWriter>
1974 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 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.
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
MCFragment * getNext() 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.
StringRef getName() const
MCSymbol * getBeginSymbol()
Represent a reference to a symbol from inside an expression.
const MCSymbol & getSymbol() const
VariantKind getKind() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
void setIndex(uint32_t Value) const
Set the (implementation defined) index.
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 ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
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.
NodeAddr< FuncNode * > Func
void write64le(void *P, uint64_t V)
void write32le(void *P, uint32_t V)
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
const unsigned WASM_SYMBOL_UNDEFINED
const uint32_t WasmPageSize
@ WASM_LIMITS_FLAG_HAS_MAX
const unsigned WASM_SYMBOL_NO_STRIP
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
const unsigned WASM_SYMBOL_TLS
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 range R to container C.
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