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.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";
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.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_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);
1001void WasmObjectWriter::writeElemSection(
1003 if (TableElems.
empty())
1006 assert(IndirectFunctionTable);
1013 assert(WasmIndices.count(IndirectFunctionTable));
1014 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
1030 const uint8_t ElemKind = 0;
1038 endSection(Section);
1041void WasmObjectWriter::writeDataCountSection() {
1042 if (DataSegments.empty())
1048 endSection(Section);
1054 if (Functions.
empty())
1062 for (
const WasmFunction &Func : Functions) {
1067 FuncSection->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1068 Asm.writeSectionData(
W->OS, FuncSection, Layout);
1072 applyRelocations(CodeRelocations,
Section.ContentsOffset, Layout);
1074 endSection(Section);
1079 if (DataSegments.empty())
1087 for (
const WasmDataSegment &Segment : DataSegments) {
1098 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1099 W->OS << Segment.Data;
1103 applyRelocations(DataRelocations,
Section.ContentsOffset, Layout);
1105 endSection(Section);
1109void WasmObjectWriter::writeRelocSection(
1111 std::vector<WasmRelocationEntry> &Relocs) {
1124 Relocs, [](
const WasmRelocationEntry &
A,
const WasmRelocationEntry &
B) {
1125 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1126 (
B.Offset +
B.FixupSection->getSectionOffset());
1130 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1134 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1136 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1139 W->OS <<
char(RelEntry.Type);
1142 if (RelEntry.hasAddend())
1146 endSection(Section);
1149void WasmObjectWriter::writeCustomRelocSections() {
1150 for (
const auto &Sec : CustomSections) {
1151 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1152 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1156void WasmObjectWriter::writeLinkingMetaDataSection(
1158 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1159 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1161 startCustomSection(Section,
"linking");
1164 SectionBookkeeping SubSection;
1165 if (SymbolInfos.
size() != 0) {
1179 writeString(
Sym.Name);
1182 writeString(
Sym.Name);
1191 CustomSections[
Sym.ElementIndex].OutputIndex;
1199 endSection(SubSection);
1202 if (DataSegments.size()) {
1205 for (
const WasmDataSegment &Segment : DataSegments) {
1206 writeString(Segment.Name);
1210 endSection(SubSection);
1213 if (!InitFuncs.empty()) {
1216 for (
auto &StartFunc : InitFuncs) {
1220 endSection(SubSection);
1223 if (Comdats.size()) {
1226 for (
const auto &
C : Comdats) {
1227 writeString(
C.first);
1230 for (
const WasmComdatEntry &Entry :
C.second) {
1235 endSection(SubSection);
1238 endSection(Section);
1241void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1245 auto *Sec = CustomSection.Section;
1246 startCustomSection(Section, CustomSection.Name);
1248 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1249 Asm.writeSectionData(
W->OS, Sec, Layout);
1251 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1252 CustomSection.OutputIndex =
Section.Index;
1254 endSection(Section);
1257 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1258 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
1263 assert(TypeIndices.count(&Symbol));
1264 return TypeIndices[&
Symbol];
1269 assert(TypeIndices.count(&Symbol));
1270 return TypeIndices[&
Symbol];
1273void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1278 if (
auto *Sig =
Symbol.getSignature()) {
1286 TypeIndices[&
Symbol] = Pair.first->second;
1289 <<
" new:" << Pair.second <<
"\n");
1290 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1293void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1299 if (
auto *Sig =
Symbol.getSignature()) {
1307 TypeIndices[&
Symbol] = Pair.first->second;
1309 LLVM_DEBUG(
dbgs() <<
"registerTagType: " << Symbol <<
" new:" << Pair.second
1311 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1315 if (
Sym.isUsedInReloc() ||
Sym.isUsedInInitArray())
1318 if (
Sym.isComdat() && !
Sym.isDefined())
1321 if (
Sym.isTemporary())
1324 if (
Sym.isSection())
1327 if (
Sym.omitFromLinkingSection())
1333void WasmObjectWriter::prepareImports(
1340 MemImport.
Module =
"env";
1341 MemImport.
Field =
"__linear_memory";
1355 if (WS.isFunction()) {
1359 ": absolute addressing not supported!");
1360 registerFunctionType(*cast<MCSymbolWasm>(BS));
1364 registerTagType(WS);
1366 if (WS.isTemporary())
1370 if (!WS.isDefined() && !WS.isComdat()) {
1371 if (WS.isFunction()) {
1373 Import.Module = WS.getImportModule();
1374 Import.Field = WS.getImportName();
1376 Import.SigIndex = getFunctionType(WS);
1378 assert(WasmIndices.count(&WS) == 0);
1379 WasmIndices[&WS] = NumFunctionImports++;
1380 }
else if (WS.isGlobal()) {
1385 Import.Field = WS.getImportName();
1387 Import.Module = WS.getImportModule();
1388 Import.Global = WS.getGlobalType();
1390 assert(WasmIndices.count(&WS) == 0);
1391 WasmIndices[&WS] = NumGlobalImports++;
1392 }
else if (WS.isTag()) {
1397 Import.Module = WS.getImportModule();
1398 Import.Field = WS.getImportName();
1400 Import.SigIndex = getTagType(WS);
1402 assert(WasmIndices.count(&WS) == 0);
1403 WasmIndices[&WS] = NumTagImports++;
1404 }
else if (WS.isTable()) {
1409 Import.Module = WS.getImportModule();
1410 Import.Field = WS.getImportName();
1412 Import.Table = WS.getTableType();
1414 assert(WasmIndices.count(&WS) == 0);
1415 WasmIndices[&WS] = NumTableImports++;
1423 if (WS.isUsedInGOT()) {
1425 if (WS.isFunction())
1426 Import.Module =
"GOT.func";
1428 Import.Module =
"GOT.mem";
1429 Import.Field = WS.getName();
1433 assert(GOTIndices.count(&WS) == 0);
1434 GOTIndices[&WS] = NumGlobalImports++;
1444 uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly);
1448 return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly);
1450 return writeOneObject(Asm, Layout, DwoMode::AllSections);
1459 CustomSections.clear();
1473 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1475 if (Mode != DwoMode::DwoOnly) {
1476 prepareImports(Imports, Asm, Layout);
1491 <<
Section.getGroup() <<
"\n";);
1498 if (
Section.getKind().isText())
1502 uint32_t SegmentIndex = DataSegments.size();
1504 DataSegments.emplace_back();
1505 WasmDataSegment &Segment = DataSegments.back();
1507 Segment.InitFlags =
Section.getPassive()
1510 Segment.Offset = DataSize;
1512 addData(Segment.Data, Section);
1514 Segment.LinkingFlags =
Section.getSegmentFlags();
1515 DataSize += Segment.Data.size();
1516 Section.setSegmentIndex(SegmentIndex);
1519 Comdats[
C->getName()].emplace_back(
1524 assert(Sec.getKind().isMetadata());
1529 if (
Name.startswith(
".custom_section."))
1530 Name =
Name.substr(strlen(
".custom_section."));
1532 MCSymbol *Begin = Sec.getBeginSymbol();
1534 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1535 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1539 if (
Name ==
"producers") {
1540 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &Section);
1543 if (
Name ==
"target_features") {
1544 TargetFeaturesSection =
1545 std::make_unique<WasmCustomSection>(
Name, &Section);
1554 Comdats[
C->getName()].emplace_back(
1556 static_cast<uint32_t>(CustomSections.size())});
1559 CustomSections.emplace_back(
Name, &Section);
1563 if (Mode != DwoMode::DwoOnly) {
1568 if (S.isTemporary() && S.getName().empty())
1573 dbgs() <<
"MCSymbol: "
1576 <<
" isDefined=" << S.isDefined() <<
" isExternal="
1577 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1578 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1579 <<
" isVariable=" << WS.isVariable() <<
"\n");
1581 if (WS.isVariable())
1583 if (WS.isComdat() && !WS.isDefined())
1586 if (WS.isFunction()) {
1588 if (WS.isDefined()) {
1589 if (WS.getOffset() != 0)
1591 "function sections must contain one function each");
1594 Index = NumFunctionImports + Functions.
size();
1596 Func.SigIndex = getFunctionType(WS);
1597 Func.Section = &WS.getSection();
1598 assert(WasmIndices.count(&WS) == 0);
1599 WasmIndices[&WS] =
Index;
1604 Comdats[
C->getName()].emplace_back(
1608 if (WS.hasExportName()) {
1610 Export.Name = WS.getExportName();
1617 Index = WasmIndices.find(&WS)->second;
1622 }
else if (WS.isData()) {
1626 if (!WS.isDefined()) {
1637 if (!WS.getSize()->evaluateAsAbsolute(
Size, Layout))
1640 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1641 if (!DataSection.isWasmData())
1650 assert(DataLocations.count(&WS) == 0);
1651 DataLocations[&WS] =
Ref;
1654 }
else if (WS.isGlobal()) {
1656 if (WS.isDefined()) {
1658 Global.Type = WS.getGlobalType();
1659 Global.Index = NumGlobalImports + Globals.
size();
1660 Global.InitExpr.Extended =
false;
1661 switch (
Global.Type.Type) {
1680 assert(WasmIndices.count(&WS) == 0);
1681 WasmIndices[&WS] =
Global.Index;
1686 << WasmIndices.find(&WS)->second <<
"\n");
1688 }
else if (WS.isTable()) {
1689 if (WS.isDefined()) {
1691 Table.
Index = NumTableImports + Tables.
size();
1692 Table.
Type = WS.getTableType();
1693 assert(WasmIndices.count(&WS) == 0);
1694 WasmIndices[&WS] = Table.
Index;
1698 << WasmIndices.find(&WS)->second <<
"\n");
1699 }
else if (WS.isTag()) {
1703 if (WS.isDefined()) {
1704 Index = NumTagImports + TagTypes.
size();
1705 uint32_t SigIndex = getTagType(WS);
1706 assert(WasmIndices.count(&WS) == 0);
1707 WasmIndices[&WS] =
Index;
1711 assert(WasmIndices.count(&WS) > 0);
1713 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1726 if (!S.isVariable())
1734 ": absolute addressing not supported!");
1742 if (
Base->isFunction()) {
1745 assert(WasmIndices.count(&WS) == 0);
1746 WasmIndices[&WS] = WasmIndex;
1748 }
else if (
Base->isData()) {
1749 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1756 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Layout))
1758 const WasmDataSegment &Segment =
1759 DataSegments[DataSection.getSegmentIndex()];
1763 DataSection.getSegmentIndex(),
1766 DataLocations[&WS] =
Ref;
1788 if (!WS.isExternal() && WS.isDefined())
1790 if (WS.isUndefined())
1792 if (WS.isNoStrip()) {
1794 if (isEmscripten()) {
1798 if (WS.hasImportName())
1800 if (WS.hasExportName())
1806 Info.Name = WS.getName();
1810 assert(WasmIndices.count(&WS) > 0);
1811 Info.ElementIndex = WasmIndices.find(&WS)->second;
1812 }
else if (WS.isDefined()) {
1813 assert(DataLocations.count(&WS) > 0);
1814 Info.DataRef = DataLocations.find(&WS)->second;
1816 WS.setIndex(SymbolInfos.
size());
1821 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1825 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1826 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1827 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1828 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1829 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1830 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1832 assert(Rel.Symbol->isFunction());
1835 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1836 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1837 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1839 <<
" to table: " << TableIndex <<
"\n");
1841 registerFunctionType(*
Base);
1845 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1846 HandleReloc(RelEntry);
1847 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1848 HandleReloc(RelEntry);
1854 if (WS.getName().startswith(
".fini_array"))
1856 if (!WS.getName().startswith(
".init_array"))
1858 if (WS.getFragmentList().empty())
1862 if (WS.getFragmentList().size() != 3)
1865 auto IT = WS.begin();
1883 unsigned PrefixLength = strlen(
".init_array");
1884 if (WS.getName().size() > PrefixLength) {
1885 if (WS.getName()[PrefixLength] !=
'.')
1887 ".init_array section priority should start with '.'");
1888 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1891 const auto &DataFrag = cast<MCDataFragment>(Frag);
1893 for (
const uint8_t *
1894 P = (
const uint8_t *)Contents.
data(),
1895 *
End = (
const uint8_t *)Contents.
data() + Contents.
size();
1904 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1907 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1910 if (!TargetSym.isFunction())
1913 std::make_pair(Priority, TargetSym.getIndex()));
1920 uint32_t CodeSectionIndex, DataSectionIndex;
1921 if (Mode != DwoMode::DwoOnly) {
1923 writeImportSection(Imports, DataSize, TableElems.
size());
1924 writeFunctionSection(Functions);
1925 writeTableSection(Tables);
1927 writeTagSection(TagTypes);
1928 writeGlobalSection(Globals);
1929 writeExportSection(Exports);
1930 const MCSymbol *IndirectFunctionTable =
1931 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1932 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1934 writeDataCountSection();
1936 CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
1937 DataSectionIndex = writeDataSection(Layout);
1942 for (
auto &Group : Comdats) {
1943 for (
auto &Entry : Group.second) {
1945 Entry.Index += SectionCount;
1949 for (
auto &CustomSection : CustomSections)
1950 writeCustomSection(CustomSection, Asm, Layout);
1952 if (Mode != DwoMode::DwoOnly) {
1953 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1955 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1956 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1958 writeCustomRelocSections();
1959 if (ProducersSection)
1960 writeCustomSection(*ProducersSection, Asm, Layout);
1961 if (TargetFeaturesSection)
1962 writeCustomSection(*TargetFeaturesSection, Asm, Layout);
1965 return W->OS.tell() - StartOffset;
1968std::unique_ptr<MCObjectWriter>
1971 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS);
1974std::unique_ptr<MCObjectWriter>
1978 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 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
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
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 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.
NodeAddr< FuncNode * > Func
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
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND
const unsigned WASM_SYMBOL_TLS
@ WASM_LIMITS_FLAG_HAS_MAX
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
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
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