16#include "llvm/Config/llvm-config.h"
36#define DEBUG_TYPE "mc"
42static const uint32_t InitialTableOffset = 1;
47struct SectionBookkeeping {
61struct WasmDataSegment {
86struct WasmComdatEntry {
92struct WasmRelocationEntry {
100 int64_t Addend,
unsigned Type,
102 : Offset(Offset), Symbol(Symbol), Addend(Addend),
Type(
Type),
103 FixupSection(FixupSection) {}
109 <<
", Sym=" << *Symbol <<
", Addend=" << Addend
110 <<
", FixupSection=" << FixupSection->
getName();
113#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
120struct WasmCustomSection {
129 : Name(Name), Section(Section) {}
141template <
typename T,
int W>
151template <
typename T,
int W>
161 writePatchableULEB<uint32_t, 5>(Stream,
Value,
Offset);
166 writePatchableSLEB<int32_t, 5>(Stream,
Value,
Offset);
171 writePatchableSLEB<uint64_t, 10>(Stream,
Value,
Offset);
176 writePatchableSLEB<int64_t, 10>(Stream,
Value,
Offset);
202 std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
205 std::vector<WasmRelocationEntry> CodeRelocations;
207 std::vector<WasmRelocationEntry> DataRelocations;
224 std::vector<WasmCustomSection> CustomSections;
225 std::unique_ptr<WasmCustomSection> ProducersSection;
226 std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
229 CustomSectionsRelocations;
237 unsigned NumFunctionImports = 0;
238 unsigned NumGlobalImports = 0;
239 unsigned NumTableImports = 0;
240 unsigned NumTagImports = 0;
248 bool IsSplitDwarf =
false;
253 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
254 bool isEmscripten()
const {
return TargetObjectWriter->isEmscripten(); }
256 void startSection(SectionBookkeeping &Section,
unsigned SectionId);
257 void startCustomSection(SectionBookkeeping &Section,
StringRef Name);
258 void endSection(SectionBookkeeping &Section);
261 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
263 : TargetObjectWriter(std::move(MOTW)),
OS(&OS_) {}
265 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
267 : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(
true),
OS(&OS_),
271 void reset()
override {
272 CodeRelocations.clear();
273 DataRelocations.clear();
277 TableIndices.
clear();
278 DataLocations.
clear();
279 CustomSections.clear();
280 ProducersSection.reset();
281 TargetFeaturesSection.reset();
282 CustomSectionsRelocations.
clear();
283 SignatureIndices.
clear();
285 DataSegments.
clear();
286 SectionFunctions.
clear();
287 NumFunctionImports = 0;
288 NumGlobalImports = 0;
311 void writeStringWithAlignment(
const StringRef Str,
unsigned Alignment);
313 void writeI32(int32_t val) {
316 W->OS.write(Buffer,
sizeof(Buffer));
319 void writeI64(int64_t val) {
322 W->OS.write(Buffer,
sizeof(Buffer));
325 void writeValueType(
wasm::ValType Ty) { W->OS <<
static_cast<char>(Ty); }
332 void writeElemSection(
const MCSymbolWasm *IndirectFunctionTable,
334 void writeDataCountSection();
342 std::vector<WasmRelocationEntry> &Relocations);
343 void writeLinkingMetaDataSection(
345 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
346 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats);
347 void writeCustomSection(WasmCustomSection &CustomSection,
349 void writeCustomRelocSections();
352 const WasmRelocationEntry &RelEntry);
356 uint32_t getRelocationIndexValue(
const WasmRelocationEntry &RelEntry);
366void WasmObjectWriter::startSection(SectionBookkeeping &Section,
367 unsigned SectionId) {
369 W->OS <<
char(SectionId);
378 Section.ContentsOffset =
W->OS.tell();
379 Section.PayloadOffset =
W->OS.tell();
380 Section.Index = SectionCount++;
385void WasmObjectWriter::writeStringWithAlignment(
const StringRef Str,
386 unsigned Alignment) {
397 assert((StrSizeLength + Paddings) <= 5 &&
"too long string to align");
405void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
411 Section.PayloadOffset =
W->OS.tell();
414 if (
Name !=
"__clangast") {
418 writeStringWithAlignment(
Name, 4);
422 Section.ContentsOffset =
W->OS.tell();
427void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
447void WasmObjectWriter::writeHeader(
const MCAssembler &Asm) {
452void WasmObjectWriter::executePostLayoutBinding(
MCAssembler &Asm) {
459 if (
auto *
Sym =
Asm.getContext().lookupSymbol(
"__indirect_function_table")) {
461 if (WasmSym->isNoStrip())
469 if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
470 const auto &Sec =
static_cast<const MCSectionWasm &
>(S.getSection());
471 auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
479void WasmObjectWriter::recordRelocation(
MCAssembler &Asm,
484 assert(!(
Asm.getBackend().getFixupKindInfo(
Fixup.getKind()).Flags &
487 const auto &FixupSection = cast<MCSectionWasm>(*Fragment->
getParent());
489 uint64_t FixupOffset =
Asm.getFragmentOffset(*Fragment) +
Fixup.getOffset();
491 bool IsLocRel =
false;
495 const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
497 if (FixupSection.isText()) {
499 Twine(
"symbol '") + SymB.getName() +
500 "' unsupported subtraction expression used in "
501 "relocation in code section.");
505 if (SymB.isUndefined()) {
507 Twine(
"symbol '") + SymB.getName() +
508 "' can not be undefined in a subtraction expression");
511 const MCSection &SecB = SymB.getSection();
512 if (&SecB != &FixupSection) {
514 Twine(
"symbol '") + SymB.getName() +
515 "' can not be placed in a different section");
519 C += FixupOffset -
Asm.getSymbolOffset(SymB);
524 const auto *SymA = cast<MCSymbolWasm>(&RefA->
getSymbol());
527 if (FixupSection.getName().starts_with(
".init_array")) {
528 SymA->setUsedInInitArray();
532 if (SymA->isVariable()) {
533 const MCExpr *Expr = SymA->getVariableValue();
534 if (
const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr))
545 TargetObjectWriter->getRelocType(
Target,
Fixup, FixupSection, IsLocRel);
550 if ((
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
551 Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
552 Type == wasm::R_WASM_SECTION_OFFSET_I32) &&
559 if (!FixupSection.isMetadata())
561 "only supported in metadata sections");
563 const MCSymbol *SectionSymbol =
nullptr;
564 const MCSection &SecA = SymA->getSection();
566 auto SecSymIt = SectionFunctions.find(&SecA);
567 if (SecSymIt == SectionFunctions.end())
569 SectionSymbol = SecSymIt->second;
576 C +=
Asm.getSymbolOffset(*SymA);
577 SymA = cast<MCSymbolWasm>(SectionSymbol);
580 if (
Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
581 Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 ||
582 Type == wasm::R_WASM_TABLE_INDEX_SLEB ||
583 Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||
584 Type == wasm::R_WASM_TABLE_INDEX_I32 ||
585 Type == wasm::R_WASM_TABLE_INDEX_I64) {
588 auto TableName =
"__indirect_function_table";
593 if (!
Sym->isFunctionTable())
603 if (
Type != wasm::R_WASM_TYPE_INDEX_LEB) {
604 if (SymA->getName().empty())
606 "supported by wasm");
608 SymA->setUsedInReloc();
614 SymA->setUsedInGOT();
620 WasmRelocationEntry Rec(FixupOffset, SymA,
C,
Type, &FixupSection);
623 if (FixupSection.isWasmData()) {
624 DataRelocations.push_back(Rec);
625 }
else if (FixupSection.isText()) {
626 CodeRelocations.push_back(Rec);
627 }
else if (FixupSection.isMetadata()) {
628 CustomSectionsRelocations[&FixupSection].push_back(Rec);
639WasmObjectWriter::getProvisionalValue(
const MCAssembler &Asm,
640 const WasmRelocationEntry &RelEntry) {
641 if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
642 RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
643 !RelEntry.Symbol->isGlobal()) {
644 assert(GOTIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in GOT index space");
645 return GOTIndices[RelEntry.Symbol];
648 switch (RelEntry.Type) {
649 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
650 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
651 case wasm::R_WASM_TABLE_INDEX_SLEB:
652 case wasm::R_WASM_TABLE_INDEX_SLEB64:
653 case wasm::R_WASM_TABLE_INDEX_I32:
654 case wasm::R_WASM_TABLE_INDEX_I64: {
657 cast<MCSymbolWasm>(
Asm.getBaseSymbol(*RelEntry.Symbol));
659 if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
660 RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
661 return TableIndices[
Base] - InitialTableOffset;
663 return TableIndices[
Base];
665 case wasm::R_WASM_TYPE_INDEX_LEB:
667 return getRelocationIndexValue(RelEntry);
668 case wasm::R_WASM_FUNCTION_INDEX_LEB:
669 case wasm::R_WASM_FUNCTION_INDEX_I32:
670 case wasm::R_WASM_GLOBAL_INDEX_LEB:
671 case wasm::R_WASM_GLOBAL_INDEX_I32:
672 case wasm::R_WASM_TAG_INDEX_LEB:
673 case wasm::R_WASM_TABLE_NUMBER_LEB:
675 assert(WasmIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in wasm index space");
676 return WasmIndices[RelEntry.Symbol];
677 case wasm::R_WASM_FUNCTION_OFFSET_I32:
678 case wasm::R_WASM_FUNCTION_OFFSET_I64:
679 case wasm::R_WASM_SECTION_OFFSET_I32: {
680 if (!RelEntry.Symbol->isDefined())
683 static_cast<const MCSectionWasm &
>(RelEntry.Symbol->getSection());
684 return Section.getSectionOffset() + RelEntry.Addend;
686 case wasm::R_WASM_MEMORY_ADDR_LEB:
687 case wasm::R_WASM_MEMORY_ADDR_LEB64:
688 case wasm::R_WASM_MEMORY_ADDR_SLEB:
689 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
690 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
691 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
692 case wasm::R_WASM_MEMORY_ADDR_I32:
693 case wasm::R_WASM_MEMORY_ADDR_I64:
694 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
695 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
696 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {
699 if (!RelEntry.Symbol->isDefined())
702 const WasmDataSegment &Segment = DataSegments[SymRef.
Segment];
704 return Segment.Offset + SymRef.
Offset + RelEntry.Addend;
718 if (Frag.hasInstructions())
721 if (
auto *
Align = dyn_cast<MCAlignFragment>(&Frag)) {
722 if (
Align->getValueSize() != 1)
728 DataBytes.
size() +
Align->getMaxBytesToEmit());
730 }
else if (
auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
732 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
734 DataBytes.
insert(DataBytes.
end(), Fill->getValueSize() * NumValues,
736 }
else if (
auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
747WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
748 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
749 if (!TypeIndices.count(RelEntry.Symbol))
751 RelEntry.Symbol->getName());
752 return TypeIndices[RelEntry.Symbol];
755 return RelEntry.Symbol->getIndex();
760void WasmObjectWriter::applyRelocations(
764 for (
const WasmRelocationEntry &RelEntry : Relocations) {
766 RelEntry.FixupSection->getSectionOffset() +
772 switch (RelEntry.Type) {
773 case wasm::R_WASM_FUNCTION_INDEX_LEB:
774 case wasm::R_WASM_TYPE_INDEX_LEB:
775 case wasm::R_WASM_GLOBAL_INDEX_LEB:
776 case wasm::R_WASM_MEMORY_ADDR_LEB:
777 case wasm::R_WASM_TAG_INDEX_LEB:
778 case wasm::R_WASM_TABLE_NUMBER_LEB:
781 case wasm::R_WASM_MEMORY_ADDR_LEB64:
784 case wasm::R_WASM_TABLE_INDEX_I32:
785 case wasm::R_WASM_MEMORY_ADDR_I32:
786 case wasm::R_WASM_FUNCTION_OFFSET_I32:
787 case wasm::R_WASM_FUNCTION_INDEX_I32:
788 case wasm::R_WASM_SECTION_OFFSET_I32:
789 case wasm::R_WASM_GLOBAL_INDEX_I32:
790 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
793 case wasm::R_WASM_TABLE_INDEX_I64:
794 case wasm::R_WASM_MEMORY_ADDR_I64:
795 case wasm::R_WASM_FUNCTION_OFFSET_I64:
798 case wasm::R_WASM_TABLE_INDEX_SLEB:
799 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
800 case wasm::R_WASM_MEMORY_ADDR_SLEB:
801 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
802 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
805 case wasm::R_WASM_TABLE_INDEX_SLEB64:
806 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
807 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
808 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
809 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
818void WasmObjectWriter::writeTypeSection(
854 writeString(
Import.Module);
855 writeString(
Import.Field);
888 if (Functions.
empty())
895 for (
const WasmFunction &Func : Functions)
902 if (TagTypes.
empty())
928 if (
Global.InitExpr.Extended) {
932 switch (
Global.Type.Type) {
946 writeValueType(wasm::ValType::EXTERNREF);
967 assert(Table.Type.ElemType != wasm::ValType::OTHERREF &&
968 "Cannot encode general ref-typed tables");
995void WasmObjectWriter::writeElemSection(
997 if (TableElems.
empty())
1000 assert(IndirectFunctionTable);
1007 assert(WasmIndices.count(IndirectFunctionTable));
1008 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
1033 endSection(Section);
1036void WasmObjectWriter::writeDataCountSection() {
1037 if (DataSegments.empty())
1043 endSection(Section);
1048 if (Functions.
empty())
1056 for (
const WasmFunction &Func : Functions) {
1059 int64_t
Size =
Asm.getSectionAddressSize(*FuncSection);
1061 FuncSection->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1062 Asm.writeSectionData(
W->OS, FuncSection);
1066 applyRelocations(CodeRelocations,
Section.ContentsOffset, Asm);
1068 endSection(Section);
1073 if (DataSegments.empty())
1081 for (
const WasmDataSegment &Segment : DataSegments) {
1092 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1093 W->OS << Segment.Data;
1097 applyRelocations(DataRelocations,
Section.ContentsOffset, Asm);
1099 endSection(Section);
1103void WasmObjectWriter::writeRelocSection(
1105 std::vector<WasmRelocationEntry> &Relocs) {
1118 Relocs, [](
const WasmRelocationEntry &
A,
const WasmRelocationEntry &
B) {
1119 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1120 (
B.Offset +
B.FixupSection->getSectionOffset());
1124 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1128 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1130 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1133 W->OS <<
char(RelEntry.Type);
1136 if (RelEntry.hasAddend())
1140 endSection(Section);
1143void WasmObjectWriter::writeCustomRelocSections() {
1144 for (
const auto &Sec : CustomSections) {
1145 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1146 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1150void WasmObjectWriter::writeLinkingMetaDataSection(
1152 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1153 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1155 startCustomSection(Section,
"linking");
1158 SectionBookkeeping SubSection;
1159 if (SymbolInfos.
size() != 0) {
1173 writeString(
Sym.Name);
1176 writeString(
Sym.Name);
1185 CustomSections[
Sym.ElementIndex].OutputIndex;
1193 endSection(SubSection);
1196 if (DataSegments.size()) {
1199 for (
const WasmDataSegment &Segment : DataSegments) {
1200 writeString(Segment.Name);
1204 endSection(SubSection);
1207 if (!InitFuncs.empty()) {
1210 for (
auto &StartFunc : InitFuncs) {
1214 endSection(SubSection);
1217 if (Comdats.size()) {
1220 for (
const auto &
C : Comdats) {
1221 writeString(
C.first);
1224 for (
const WasmComdatEntry &Entry :
C.second) {
1229 endSection(SubSection);
1232 endSection(Section);
1235void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1238 auto *Sec = CustomSection.Section;
1239 startCustomSection(Section, CustomSection.Name);
1241 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1242 Asm.writeSectionData(
W->OS, Sec);
1244 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1245 CustomSection.OutputIndex =
Section.Index;
1247 endSection(Section);
1250 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1251 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Asm);
1256 assert(TypeIndices.count(&Symbol));
1257 return TypeIndices[&
Symbol];
1262 assert(TypeIndices.count(&Symbol));
1263 return TypeIndices[&
Symbol];
1266void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1271 if (
auto *Sig =
Symbol.getSignature()) {
1279 TypeIndices[&
Symbol] = Pair.first->second;
1282 <<
" new:" << Pair.second <<
"\n");
1283 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1286void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1292 if (
auto *Sig =
Symbol.getSignature()) {
1300 TypeIndices[&
Symbol] = Pair.first->second;
1302 LLVM_DEBUG(
dbgs() <<
"registerTagType: " << Symbol <<
" new:" << Pair.second
1304 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1308 if (
Sym.isUsedInReloc() ||
Sym.isUsedInInitArray())
1311 if (
Sym.isComdat() && !
Sym.isDefined())
1314 if (
Sym.isTemporary())
1317 if (
Sym.isSection())
1320 if (
Sym.omitFromLinkingSection())
1329 for (
const MCSymbol &S : Asm.symbols()) {
1331 if (WS.isData() && WS.isInSection()) {
1332 auto &RefSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1342void WasmObjectWriter::prepareImports(
1348 MemImport.
Module =
"env";
1349 MemImport.
Field =
"__linear_memory";
1363 if (WS.isFunction()) {
1364 const auto *BS =
Asm.getBaseSymbol(S);
1367 ": absolute addressing not supported!");
1368 registerFunctionType(*cast<MCSymbolWasm>(BS));
1372 registerTagType(WS);
1374 if (WS.isTemporary())
1378 if (!WS.isDefined() && !WS.isComdat()) {
1379 if (WS.isFunction()) {
1381 Import.Module = WS.getImportModule();
1382 Import.Field = WS.getImportName();
1384 Import.SigIndex = getFunctionType(WS);
1386 assert(WasmIndices.count(&WS) == 0);
1387 WasmIndices[&WS] = NumFunctionImports++;
1388 }
else if (WS.isGlobal()) {
1393 Import.Field = WS.getImportName();
1395 Import.Module = WS.getImportModule();
1396 Import.Global = WS.getGlobalType();
1398 assert(WasmIndices.count(&WS) == 0);
1399 WasmIndices[&WS] = NumGlobalImports++;
1400 }
else if (WS.isTag()) {
1405 Import.Module = WS.getImportModule();
1406 Import.Field = WS.getImportName();
1408 Import.SigIndex = getTagType(WS);
1410 assert(WasmIndices.count(&WS) == 0);
1411 WasmIndices[&WS] = NumTagImports++;
1412 }
else if (WS.isTable()) {
1417 Import.Module = WS.getImportModule();
1418 Import.Field = WS.getImportName();
1420 Import.Table = WS.getTableType();
1422 assert(WasmIndices.count(&WS) == 0);
1423 WasmIndices[&WS] = NumTableImports++;
1431 if (WS.isUsedInGOT()) {
1433 if (WS.isFunction())
1434 Import.Module =
"GOT.func";
1436 Import.Module =
"GOT.mem";
1437 Import.Field = WS.getName();
1441 assert(GOTIndices.count(&WS) == 0);
1442 GOTIndices[&WS] = NumGlobalImports++;
1451 uint64_t TotalSize = writeOneObject(Asm, DwoMode::NonDwoOnly);
1455 return TotalSize + writeOneObject(Asm, DwoMode::DwoOnly);
1457 return writeOneObject(Asm, DwoMode::AllSections);
1465 CustomSections.clear();
1479 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1481 if (Mode != DwoMode::DwoOnly)
1482 prepareImports(Imports, Asm);
1496 <<
Section.getGroup() <<
"\n";);
1509 uint32_t SegmentIndex = DataSegments.size();
1511 DataSegments.emplace_back();
1512 WasmDataSegment &Segment = DataSegments.back();
1514 Segment.InitFlags =
Section.getPassive()
1517 Segment.Offset = DataSize;
1519 addData(Segment.Data, Section);
1521 Segment.LinkingFlags =
Section.getSegmentFlags();
1522 DataSize += Segment.Data.size();
1523 Section.setSegmentIndex(SegmentIndex);
1526 Comdats[
C->getName()].emplace_back(
1536 Name.consume_front(
".custom_section.");
1538 MCSymbol *Begin = Sec.getBeginSymbol();
1540 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1541 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1545 if (
Name ==
"producers") {
1546 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &Section);
1549 if (
Name ==
"target_features") {
1550 TargetFeaturesSection =
1551 std::make_unique<WasmCustomSection>(
Name, &Section);
1560 Comdats[
C->getName()].emplace_back(
1562 static_cast<uint32_t>(CustomSections.size())});
1565 CustomSections.emplace_back(
Name, &Section);
1569 if (Mode != DwoMode::DwoOnly) {
1574 if (S.isTemporary() && S.getName().empty())
1579 dbgs() <<
"MCSymbol: "
1582 <<
" isDefined=" << S.isDefined() <<
" isExternal="
1583 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1584 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1585 <<
" isVariable=" << WS.isVariable() <<
"\n");
1587 if (WS.isVariable())
1589 if (WS.isComdat() && !WS.isDefined())
1592 if (WS.isFunction()) {
1594 if (WS.isDefined()) {
1595 if (WS.getOffset() != 0)
1597 "function sections must contain one function each");
1600 Index = NumFunctionImports + Functions.
size();
1602 Func.SigIndex = getFunctionType(WS);
1603 Func.Section = &WS.getSection();
1604 assert(WasmIndices.count(&WS) == 0);
1605 WasmIndices[&WS] =
Index;
1610 Comdats[
C->getName()].emplace_back(
1614 if (WS.hasExportName()) {
1616 Export.Name = WS.getExportName();
1623 Index = WasmIndices.find(&WS)->second;
1628 }
else if (WS.isData()) {
1632 if (!WS.isDefined()) {
1643 if (!WS.getSize()->evaluateAsAbsolute(
Size, Asm))
1646 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1647 if (!DataSection.isWasmData())
1654 DataSection.getSegmentIndex(),
Asm.getSymbolOffset(WS),
1656 assert(DataLocations.count(&WS) == 0);
1657 DataLocations[&WS] =
Ref;
1660 }
else if (WS.isGlobal()) {
1662 if (WS.isDefined()) {
1664 Global.Type = WS.getGlobalType();
1665 Global.Index = NumGlobalImports + Globals.
size();
1666 Global.InitExpr.Extended =
false;
1667 switch (
Global.Type.Type) {
1686 assert(WasmIndices.count(&WS) == 0);
1687 WasmIndices[&WS] =
Global.Index;
1692 << WasmIndices.find(&WS)->second <<
"\n");
1694 }
else if (WS.isTable()) {
1695 if (WS.isDefined()) {
1697 Table.
Index = NumTableImports + Tables.
size();
1698 Table.
Type = WS.getTableType();
1699 assert(WasmIndices.count(&WS) == 0);
1700 WasmIndices[&WS] = Table.
Index;
1704 << WasmIndices.find(&WS)->second <<
"\n");
1705 }
else if (WS.isTag()) {
1709 if (WS.isDefined()) {
1710 Index = NumTagImports + TagTypes.
size();
1711 uint32_t SigIndex = getTagType(WS);
1712 assert(WasmIndices.count(&WS) == 0);
1713 WasmIndices[&WS] =
Index;
1717 assert(WasmIndices.count(&WS) > 0);
1719 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1732 if (!S.isVariable())
1737 const auto *BS =
Asm.getBaseSymbol(S);
1740 ": absolute addressing not supported!");
1748 if (
Base->isFunction()) {
1751 assert(WasmIndices.count(&WS) == 0);
1752 WasmIndices[&WS] = WasmIndex;
1754 }
else if (
Base->isData()) {
1755 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1762 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Asm))
1764 const WasmDataSegment &Segment =
1765 DataSegments[DataSection.getSegmentIndex()];
1769 DataSection.getSegmentIndex(),
1772 DataLocations[&WS] =
Ref;
1794 if (!WS.isExternal() && WS.isDefined())
1796 if (WS.isUndefined())
1798 if (WS.isNoStrip()) {
1800 if (isEmscripten()) {
1804 if (WS.hasImportName())
1806 if (WS.hasExportName())
1812 Info.Name = WS.getName();
1816 assert(WasmIndices.count(&WS) > 0);
1817 Info.ElementIndex = WasmIndices.find(&WS)->second;
1818 }
else if (WS.isDefined()) {
1819 assert(DataLocations.count(&WS) > 0);
1820 Info.DataRef = DataLocations.find(&WS)->second;
1822 WS.setIndex(SymbolInfos.
size());
1827 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1831 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1832 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1833 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1834 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1835 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1836 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1838 assert(Rel.Symbol->isFunction());
1840 cast<MCSymbolWasm>(
Asm.getBaseSymbol(*Rel.Symbol));
1841 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1842 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1843 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1845 <<
" to table: " << TableIndex <<
"\n");
1847 registerFunctionType(*
Base);
1851 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1852 HandleReloc(RelEntry);
1853 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1854 HandleReloc(RelEntry);
1860 if (WS.getName().starts_with(
".fini_array"))
1862 if (!WS.getName().starts_with(
".init_array"))
1864 auto IT = WS.begin();
1872 while (nextFrag !=
nullptr) {
1876 if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
1879 ".init_array section should be aligned for pointers");
1887 unsigned PrefixLength = strlen(
".init_array");
1888 if (WS.getName().size() > PrefixLength) {
1889 if (WS.getName()[PrefixLength] !=
'.')
1891 ".init_array section priority should start with '.'");
1892 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1895 const auto &DataFrag = cast<MCDataFragment>(Frag);
1901 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1904 "fixups in .init_array should be symbol references");
1905 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1908 if (!TargetSym.isFunction())
1910 InitFuncs.
push_back(std::make_pair(Priority, TargetSym.getIndex()));
1918 uint32_t CodeSectionIndex, DataSectionIndex;
1919 if (Mode != DwoMode::DwoOnly) {
1921 writeImportSection(Imports, DataSize, TableElems.
size());
1922 writeFunctionSection(Functions);
1923 writeTableSection(Tables);
1925 writeTagSection(TagTypes);
1926 writeGlobalSection(Globals);
1927 writeExportSection(Exports);
1928 const MCSymbol *IndirectFunctionTable =
1929 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1930 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1932 writeDataCountSection();
1934 CodeSectionIndex = writeCodeSection(Asm, Functions);
1935 DataSectionIndex = writeDataSection(Asm);
1940 for (
auto &Group : Comdats) {
1941 for (
auto &Entry : Group.second) {
1943 Entry.Index += SectionCount;
1947 for (
auto &CustomSection : CustomSections)
1948 writeCustomSection(CustomSection, Asm);
1950 if (Mode != DwoMode::DwoOnly) {
1951 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1953 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1954 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1956 writeCustomRelocSections();
1957 if (ProducersSection)
1958 writeCustomSection(*ProducersSection, Asm);
1959 if (TargetFeaturesSection)
1960 writeCustomSection(*TargetFeaturesSection, Asm);
1963 return W->OS.tell() - StartOffset;
1966std::unique_ptr<MCObjectWriter>
1969 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS);
1972std::unique_ptr<MCObjectWriter>
1976 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS, DwoOS);
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
PowerPC TLS Dynamic Call Fixup
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const FuncProtoTy Signatures[]
static const unsigned InvalidIndex
static bool isSectionReferenced(MCAssembler &Asm, MCSectionWasm &Section)
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.
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 void executePostLayoutBinding(MCAssembler &Asm)
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
virtual void reset()
lifetime management
virtual uint64_t writeObject(MCAssembler &Asm)=0
Write the object file and returns the number of bytes written.
virtual void recordRelocation(MCAssembler &Asm, 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)
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.
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_ELEM_SEGMENT_HAS_TABLE_NUMBER
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
@ WASM_LIMITS_FLAG_HAS_MAX
bool relocTypeHasAddend(uint32_t type)
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
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)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
@ 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.
const char * toString(DWARFSectionKind Kind)
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