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().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.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);
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;
1032 const uint8_t ElemKind = 0;
1040 endSection(Section);
1043void WasmObjectWriter::writeDataCountSection() {
1044 if (DataSegments.empty())
1050 endSection(Section);
1056 if (Functions.
empty())
1064 for (
const WasmFunction &Func : Functions) {
1069 FuncSection->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1070 Asm.writeSectionData(
W->OS, FuncSection, Layout);
1074 applyRelocations(CodeRelocations,
Section.ContentsOffset, Layout);
1076 endSection(Section);
1081 if (DataSegments.empty())
1089 for (
const WasmDataSegment &Segment : DataSegments) {
1100 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1101 W->OS << Segment.Data;
1105 applyRelocations(DataRelocations,
Section.ContentsOffset, Layout);
1107 endSection(Section);
1111void WasmObjectWriter::writeRelocSection(
1113 std::vector<WasmRelocationEntry> &Relocs) {
1126 Relocs, [](
const WasmRelocationEntry &
A,
const WasmRelocationEntry &
B) {
1127 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1128 (
B.Offset +
B.FixupSection->getSectionOffset());
1132 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1136 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1138 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1141 W->OS <<
char(RelEntry.Type);
1144 if (RelEntry.hasAddend())
1148 endSection(Section);
1151void WasmObjectWriter::writeCustomRelocSections() {
1152 for (
const auto &Sec : CustomSections) {
1153 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1154 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1158void WasmObjectWriter::writeLinkingMetaDataSection(
1160 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1161 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1163 startCustomSection(Section,
"linking");
1166 SectionBookkeeping SubSection;
1167 if (SymbolInfos.
size() != 0) {
1181 writeString(
Sym.Name);
1184 writeString(
Sym.Name);
1193 CustomSections[
Sym.ElementIndex].OutputIndex;
1201 endSection(SubSection);
1204 if (DataSegments.size()) {
1207 for (
const WasmDataSegment &Segment : DataSegments) {
1208 writeString(Segment.Name);
1212 endSection(SubSection);
1215 if (!InitFuncs.empty()) {
1218 for (
auto &StartFunc : InitFuncs) {
1222 endSection(SubSection);
1225 if (Comdats.size()) {
1228 for (
const auto &
C : Comdats) {
1229 writeString(
C.first);
1232 for (
const WasmComdatEntry &Entry :
C.second) {
1237 endSection(SubSection);
1240 endSection(Section);
1243void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1247 auto *Sec = CustomSection.Section;
1248 startCustomSection(Section, CustomSection.Name);
1250 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1251 Asm.writeSectionData(
W->OS, Sec, Layout);
1253 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1254 CustomSection.OutputIndex =
Section.Index;
1256 endSection(Section);
1259 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1260 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
1265 assert(TypeIndices.count(&Symbol));
1266 return TypeIndices[&
Symbol];
1271 assert(TypeIndices.count(&Symbol));
1272 return TypeIndices[&
Symbol];
1275void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1280 if (
auto *Sig =
Symbol.getSignature()) {
1288 TypeIndices[&
Symbol] = Pair.first->second;
1291 <<
" new:" << Pair.second <<
"\n");
1292 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1295void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1301 if (
auto *Sig =
Symbol.getSignature()) {
1309 TypeIndices[&
Symbol] = Pair.first->second;
1311 LLVM_DEBUG(
dbgs() <<
"registerTagType: " << Symbol <<
" new:" << Pair.second
1313 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1317 if (
Sym.isUsedInReloc() ||
Sym.isUsedInInitArray())
1320 if (
Sym.isComdat() && !
Sym.isDefined())
1323 if (
Sym.isTemporary())
1326 if (
Sym.isSection())
1329 if (
Sym.omitFromLinkingSection())
1335void WasmObjectWriter::prepareImports(
1342 MemImport.
Module =
"env";
1343 MemImport.
Field =
"__linear_memory";
1357 if (WS.isFunction()) {
1361 ": absolute addressing not supported!");
1362 registerFunctionType(*cast<MCSymbolWasm>(BS));
1366 registerTagType(WS);
1368 if (WS.isTemporary())
1372 if (!WS.isDefined() && !WS.isComdat()) {
1373 if (WS.isFunction()) {
1375 Import.Module = WS.getImportModule();
1376 Import.Field = WS.getImportName();
1378 Import.SigIndex = getFunctionType(WS);
1380 assert(WasmIndices.count(&WS) == 0);
1381 WasmIndices[&WS] = NumFunctionImports++;
1382 }
else if (WS.isGlobal()) {
1387 Import.Field = WS.getImportName();
1389 Import.Module = WS.getImportModule();
1390 Import.Global = WS.getGlobalType();
1392 assert(WasmIndices.count(&WS) == 0);
1393 WasmIndices[&WS] = NumGlobalImports++;
1394 }
else if (WS.isTag()) {
1399 Import.Module = WS.getImportModule();
1400 Import.Field = WS.getImportName();
1402 Import.SigIndex = getTagType(WS);
1404 assert(WasmIndices.count(&WS) == 0);
1405 WasmIndices[&WS] = NumTagImports++;
1406 }
else if (WS.isTable()) {
1411 Import.Module = WS.getImportModule();
1412 Import.Field = WS.getImportName();
1414 Import.Table = WS.getTableType();
1416 assert(WasmIndices.count(&WS) == 0);
1417 WasmIndices[&WS] = NumTableImports++;
1425 if (WS.isUsedInGOT()) {
1427 if (WS.isFunction())
1428 Import.Module =
"GOT.func";
1430 Import.Module =
"GOT.mem";
1431 Import.Field = WS.getName();
1435 assert(GOTIndices.count(&WS) == 0);
1436 GOTIndices[&WS] = NumGlobalImports++;
1446 uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly);
1450 return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly);
1452 return writeOneObject(Asm, Layout, DwoMode::AllSections);
1461 CustomSections.clear();
1475 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1477 if (Mode != DwoMode::DwoOnly) {
1478 prepareImports(Imports, Asm, Layout);
1493 <<
Section.getGroup() <<
"\n";);
1500 if (
Section.getKind().isText())
1504 uint32_t SegmentIndex = DataSegments.size();
1506 DataSegments.emplace_back();
1507 WasmDataSegment &Segment = DataSegments.back();
1509 Segment.InitFlags =
Section.getPassive()
1512 Segment.Offset = DataSize;
1514 addData(Segment.Data, Section);
1516 Segment.LinkingFlags =
Section.getSegmentFlags();
1517 DataSize += Segment.Data.size();
1518 Section.setSegmentIndex(SegmentIndex);
1521 Comdats[
C->getName()].emplace_back(
1526 assert(Sec.getKind().isMetadata());
1531 Name.consume_front(
".custom_section.");
1533 MCSymbol *Begin = Sec.getBeginSymbol();
1535 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1536 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1540 if (
Name ==
"producers") {
1541 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &Section);
1544 if (
Name ==
"target_features") {
1545 TargetFeaturesSection =
1546 std::make_unique<WasmCustomSection>(
Name, &Section);
1555 Comdats[
C->getName()].emplace_back(
1557 static_cast<uint32_t>(CustomSections.size())});
1560 CustomSections.emplace_back(
Name, &Section);
1564 if (Mode != DwoMode::DwoOnly) {
1569 if (S.isTemporary() && S.getName().empty())
1574 dbgs() <<
"MCSymbol: "
1577 <<
" isDefined=" << S.isDefined() <<
" isExternal="
1578 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1579 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1580 <<
" isVariable=" << WS.isVariable() <<
"\n");
1582 if (WS.isVariable())
1584 if (WS.isComdat() && !WS.isDefined())
1587 if (WS.isFunction()) {
1589 if (WS.isDefined()) {
1590 if (WS.getOffset() != 0)
1592 "function sections must contain one function each");
1595 Index = NumFunctionImports + Functions.
size();
1597 Func.SigIndex = getFunctionType(WS);
1598 Func.Section = &WS.getSection();
1599 assert(WasmIndices.count(&WS) == 0);
1600 WasmIndices[&WS] =
Index;
1605 Comdats[
C->getName()].emplace_back(
1609 if (WS.hasExportName()) {
1611 Export.Name = WS.getExportName();
1618 Index = WasmIndices.find(&WS)->second;
1623 }
else if (WS.isData()) {
1627 if (!WS.isDefined()) {
1638 if (!WS.getSize()->evaluateAsAbsolute(
Size, Layout))
1641 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1642 if (!DataSection.isWasmData())
1651 assert(DataLocations.count(&WS) == 0);
1652 DataLocations[&WS] =
Ref;
1655 }
else if (WS.isGlobal()) {
1657 if (WS.isDefined()) {
1659 Global.Type = WS.getGlobalType();
1660 Global.Index = NumGlobalImports + Globals.
size();
1661 Global.InitExpr.Extended =
false;
1662 switch (
Global.Type.Type) {
1681 assert(WasmIndices.count(&WS) == 0);
1682 WasmIndices[&WS] =
Global.Index;
1687 << WasmIndices.find(&WS)->second <<
"\n");
1689 }
else if (WS.isTable()) {
1690 if (WS.isDefined()) {
1692 Table.
Index = NumTableImports + Tables.
size();
1693 Table.
Type = WS.getTableType();
1694 assert(WasmIndices.count(&WS) == 0);
1695 WasmIndices[&WS] = Table.
Index;
1699 << WasmIndices.find(&WS)->second <<
"\n");
1700 }
else if (WS.isTag()) {
1704 if (WS.isDefined()) {
1705 Index = NumTagImports + TagTypes.
size();
1706 uint32_t SigIndex = getTagType(WS);
1707 assert(WasmIndices.count(&WS) == 0);
1708 WasmIndices[&WS] =
Index;
1712 assert(WasmIndices.count(&WS) > 0);
1714 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1727 if (!S.isVariable())
1735 ": absolute addressing not supported!");
1743 if (
Base->isFunction()) {
1746 assert(WasmIndices.count(&WS) == 0);
1747 WasmIndices[&WS] = WasmIndex;
1749 }
else if (
Base->isData()) {
1750 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1757 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Layout))
1759 const WasmDataSegment &Segment =
1760 DataSegments[DataSection.getSegmentIndex()];
1764 DataSection.getSegmentIndex(),
1767 DataLocations[&WS] =
Ref;
1789 if (!WS.isExternal() && WS.isDefined())
1791 if (WS.isUndefined())
1793 if (WS.isNoStrip()) {
1795 if (isEmscripten()) {
1799 if (WS.hasImportName())
1801 if (WS.hasExportName())
1807 Info.Name = WS.getName();
1811 assert(WasmIndices.count(&WS) > 0);
1812 Info.ElementIndex = WasmIndices.find(&WS)->second;
1813 }
else if (WS.isDefined()) {
1814 assert(DataLocations.count(&WS) > 0);
1815 Info.DataRef = DataLocations.find(&WS)->second;
1817 WS.setIndex(SymbolInfos.
size());
1822 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1826 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1827 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1828 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1829 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1830 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1831 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1833 assert(Rel.Symbol->isFunction());
1836 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1837 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1838 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1840 <<
" to table: " << TableIndex <<
"\n");
1842 registerFunctionType(*
Base);
1846 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1847 HandleReloc(RelEntry);
1848 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1849 HandleReloc(RelEntry);
1855 if (WS.getName().starts_with(
".fini_array"))
1857 if (!WS.getName().starts_with(
".init_array"))
1859 if (WS.getFragmentList().empty())
1863 if (WS.getFragmentList().size() != 3)
1866 auto IT = WS.begin();
1884 unsigned PrefixLength = strlen(
".init_array");
1885 if (WS.getName().size() > PrefixLength) {
1886 if (WS.getName()[PrefixLength] !=
'.')
1888 ".init_array section priority should start with '.'");
1889 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1892 const auto &DataFrag = cast<MCDataFragment>(Frag);
1894 for (
const uint8_t *
1895 P = (
const uint8_t *)Contents.
data(),
1896 *
End = (
const uint8_t *)Contents.
data() + Contents.
size();
1905 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1908 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1911 if (!TargetSym.isFunction())
1914 std::make_pair(Priority, TargetSym.getIndex()));
1921 uint32_t CodeSectionIndex, DataSectionIndex;
1922 if (Mode != DwoMode::DwoOnly) {
1924 writeImportSection(Imports, DataSize, TableElems.
size());
1925 writeFunctionSection(Functions);
1926 writeTableSection(Tables);
1928 writeTagSection(TagTypes);
1929 writeGlobalSection(Globals);
1930 writeExportSection(Exports);
1931 const MCSymbol *IndirectFunctionTable =
1932 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1933 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1935 writeDataCountSection();
1937 CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
1938 DataSectionIndex = writeDataSection(Layout);
1943 for (
auto &Group : Comdats) {
1944 for (
auto &Entry : Group.second) {
1946 Entry.Index += SectionCount;
1950 for (
auto &CustomSection : CustomSections)
1951 writeCustomSection(CustomSection, Asm, Layout);
1953 if (Mode != DwoMode::DwoOnly) {
1954 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1956 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1957 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1959 writeCustomRelocSections();
1960 if (ProducersSection)
1961 writeCustomSection(*ProducersSection, Asm, Layout);
1962 if (TargetFeaturesSection)
1963 writeCustomSection(*TargetFeaturesSection, Asm, Layout);
1966 return W->OS.tell() - StartOffset;
1969std::unique_ptr<MCObjectWriter>
1972 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS);
1975std::unique_ptr<MCObjectWriter>
1979 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 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)
const unsigned WASM_SYMBOL_UNDEFINED
const uint32_t WasmPageSize
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
const unsigned WASM_SYMBOL_NO_STRIP
@ WASM_LIMITS_FLAG_HAS_MAX
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
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
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