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 auto It = TypeIndices.find(RelEntry.Symbol);
750 if (It == TypeIndices.end())
752 RelEntry.Symbol->getName());
756 return RelEntry.Symbol->getIndex();
761void WasmObjectWriter::applyRelocations(
765 for (
const WasmRelocationEntry &RelEntry : Relocations) {
767 RelEntry.FixupSection->getSectionOffset() +
773 switch (RelEntry.Type) {
774 case wasm::R_WASM_FUNCTION_INDEX_LEB:
775 case wasm::R_WASM_TYPE_INDEX_LEB:
776 case wasm::R_WASM_GLOBAL_INDEX_LEB:
777 case wasm::R_WASM_MEMORY_ADDR_LEB:
778 case wasm::R_WASM_TAG_INDEX_LEB:
779 case wasm::R_WASM_TABLE_NUMBER_LEB:
782 case wasm::R_WASM_MEMORY_ADDR_LEB64:
785 case wasm::R_WASM_TABLE_INDEX_I32:
786 case wasm::R_WASM_MEMORY_ADDR_I32:
787 case wasm::R_WASM_FUNCTION_OFFSET_I32:
788 case wasm::R_WASM_FUNCTION_INDEX_I32:
789 case wasm::R_WASM_SECTION_OFFSET_I32:
790 case wasm::R_WASM_GLOBAL_INDEX_I32:
791 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
794 case wasm::R_WASM_TABLE_INDEX_I64:
795 case wasm::R_WASM_MEMORY_ADDR_I64:
796 case wasm::R_WASM_FUNCTION_OFFSET_I64:
799 case wasm::R_WASM_TABLE_INDEX_SLEB:
800 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
801 case wasm::R_WASM_MEMORY_ADDR_SLEB:
802 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
803 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
806 case wasm::R_WASM_TABLE_INDEX_SLEB64:
807 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
808 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
809 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
810 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
819void WasmObjectWriter::writeTypeSection(
855 writeString(
Import.Module);
856 writeString(
Import.Field);
889 if (Functions.
empty())
896 for (
const WasmFunction &Func : Functions)
903 if (TagTypes.
empty())
929 if (
Global.InitExpr.Extended) {
933 switch (
Global.Type.Type) {
947 writeValueType(wasm::ValType::EXTERNREF);
968 assert(Table.Type.ElemType != wasm::ValType::OTHERREF &&
969 "Cannot encode general ref-typed tables");
996void WasmObjectWriter::writeElemSection(
998 if (TableElems.
empty())
1001 assert(IndirectFunctionTable);
1008 assert(WasmIndices.count(IndirectFunctionTable));
1009 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
1034 endSection(Section);
1037void WasmObjectWriter::writeDataCountSection() {
1038 if (DataSegments.empty())
1044 endSection(Section);
1049 if (Functions.
empty())
1057 for (
const WasmFunction &Func : Functions) {
1060 int64_t
Size =
Asm.getSectionAddressSize(*FuncSection);
1062 FuncSection->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1063 Asm.writeSectionData(
W->OS, FuncSection);
1067 applyRelocations(CodeRelocations,
Section.ContentsOffset, Asm);
1069 endSection(Section);
1074 if (DataSegments.empty())
1082 for (
const WasmDataSegment &Segment : DataSegments) {
1093 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1094 W->OS << Segment.Data;
1098 applyRelocations(DataRelocations,
Section.ContentsOffset, Asm);
1100 endSection(Section);
1104void WasmObjectWriter::writeRelocSection(
1106 std::vector<WasmRelocationEntry> &Relocs) {
1119 Relocs, [](
const WasmRelocationEntry &
A,
const WasmRelocationEntry &
B) {
1120 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1121 (
B.Offset +
B.FixupSection->getSectionOffset());
1125 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1129 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1131 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1134 W->OS <<
char(RelEntry.Type);
1137 if (RelEntry.hasAddend())
1141 endSection(Section);
1144void WasmObjectWriter::writeCustomRelocSections() {
1145 for (
const auto &Sec : CustomSections) {
1146 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1147 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1151void WasmObjectWriter::writeLinkingMetaDataSection(
1153 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1154 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1156 startCustomSection(Section,
"linking");
1159 SectionBookkeeping SubSection;
1160 if (SymbolInfos.
size() != 0) {
1174 writeString(
Sym.Name);
1177 writeString(
Sym.Name);
1186 CustomSections[
Sym.ElementIndex].OutputIndex;
1194 endSection(SubSection);
1197 if (DataSegments.size()) {
1200 for (
const WasmDataSegment &Segment : DataSegments) {
1201 writeString(Segment.Name);
1205 endSection(SubSection);
1208 if (!InitFuncs.empty()) {
1211 for (
auto &StartFunc : InitFuncs) {
1215 endSection(SubSection);
1218 if (Comdats.size()) {
1221 for (
const auto &
C : Comdats) {
1222 writeString(
C.first);
1225 for (
const WasmComdatEntry &Entry :
C.second) {
1230 endSection(SubSection);
1233 endSection(Section);
1236void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1239 auto *Sec = CustomSection.Section;
1240 startCustomSection(Section, CustomSection.Name);
1242 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1243 Asm.writeSectionData(
W->OS, Sec);
1245 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1246 CustomSection.OutputIndex =
Section.Index;
1248 endSection(Section);
1251 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1252 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Asm);
1257 assert(TypeIndices.count(&Symbol));
1258 return TypeIndices[&
Symbol];
1263 assert(TypeIndices.count(&Symbol));
1264 return TypeIndices[&
Symbol];
1267void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1272 if (
auto *Sig =
Symbol.getSignature()) {
1280 TypeIndices[&
Symbol] = Pair.first->second;
1283 <<
" new:" << Pair.second <<
"\n");
1284 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1287void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1293 if (
auto *Sig =
Symbol.getSignature()) {
1301 TypeIndices[&
Symbol] = Pair.first->second;
1303 LLVM_DEBUG(
dbgs() <<
"registerTagType: " << Symbol <<
" new:" << Pair.second
1305 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1309 if (
Sym.isUsedInReloc() ||
Sym.isUsedInInitArray())
1312 if (
Sym.isComdat() && !
Sym.isDefined())
1315 if (
Sym.isTemporary())
1318 if (
Sym.isSection())
1321 if (
Sym.omitFromLinkingSection())
1330 for (
const MCSymbol &S : Asm.symbols()) {
1332 if (WS.isData() && WS.isInSection()) {
1333 auto &RefSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1343void WasmObjectWriter::prepareImports(
1349 MemImport.
Module =
"env";
1350 MemImport.
Field =
"__linear_memory";
1364 if (WS.isFunction()) {
1365 const auto *BS =
Asm.getBaseSymbol(S);
1368 ": absolute addressing not supported!");
1369 registerFunctionType(*cast<MCSymbolWasm>(BS));
1373 registerTagType(WS);
1375 if (WS.isTemporary())
1379 if (!WS.isDefined() && !WS.isComdat()) {
1380 if (WS.isFunction()) {
1382 Import.Module = WS.getImportModule();
1383 Import.Field = WS.getImportName();
1385 Import.SigIndex = getFunctionType(WS);
1387 assert(WasmIndices.count(&WS) == 0);
1388 WasmIndices[&WS] = NumFunctionImports++;
1389 }
else if (WS.isGlobal()) {
1394 Import.Field = WS.getImportName();
1396 Import.Module = WS.getImportModule();
1397 Import.Global = WS.getGlobalType();
1399 assert(WasmIndices.count(&WS) == 0);
1400 WasmIndices[&WS] = NumGlobalImports++;
1401 }
else if (WS.isTag()) {
1406 Import.Module = WS.getImportModule();
1407 Import.Field = WS.getImportName();
1409 Import.SigIndex = getTagType(WS);
1411 assert(WasmIndices.count(&WS) == 0);
1412 WasmIndices[&WS] = NumTagImports++;
1413 }
else if (WS.isTable()) {
1418 Import.Module = WS.getImportModule();
1419 Import.Field = WS.getImportName();
1421 Import.Table = WS.getTableType();
1423 assert(WasmIndices.count(&WS) == 0);
1424 WasmIndices[&WS] = NumTableImports++;
1432 if (WS.isUsedInGOT()) {
1434 if (WS.isFunction())
1435 Import.Module =
"GOT.func";
1437 Import.Module =
"GOT.mem";
1438 Import.Field = WS.getName();
1442 assert(GOTIndices.count(&WS) == 0);
1443 GOTIndices[&WS] = NumGlobalImports++;
1452 uint64_t TotalSize = writeOneObject(Asm, DwoMode::NonDwoOnly);
1456 return TotalSize + writeOneObject(Asm, DwoMode::DwoOnly);
1458 return writeOneObject(Asm, DwoMode::AllSections);
1466 CustomSections.clear();
1480 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1482 if (Mode != DwoMode::DwoOnly)
1483 prepareImports(Imports, Asm);
1497 <<
Section.getGroup() <<
"\n";);
1510 uint32_t SegmentIndex = DataSegments.size();
1512 DataSegments.emplace_back();
1513 WasmDataSegment &Segment = DataSegments.back();
1515 Segment.InitFlags =
Section.getPassive()
1518 Segment.Offset = DataSize;
1520 addData(Segment.Data, Section);
1522 Segment.LinkingFlags =
Section.getSegmentFlags();
1523 DataSize += Segment.Data.size();
1524 Section.setSegmentIndex(SegmentIndex);
1527 Comdats[
C->getName()].emplace_back(
1537 Name.consume_front(
".custom_section.");
1539 MCSymbol *Begin = Sec.getBeginSymbol();
1541 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1542 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1546 if (
Name ==
"producers") {
1547 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &Section);
1550 if (
Name ==
"target_features") {
1551 TargetFeaturesSection =
1552 std::make_unique<WasmCustomSection>(
Name, &Section);
1561 Comdats[
C->getName()].emplace_back(
1563 static_cast<uint32_t>(CustomSections.size())});
1566 CustomSections.emplace_back(
Name, &Section);
1570 if (Mode != DwoMode::DwoOnly) {
1575 if (S.isTemporary() && S.getName().empty())
1580 dbgs() <<
"MCSymbol: "
1583 <<
" isDefined=" << S.isDefined() <<
" isExternal="
1584 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1585 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1586 <<
" isVariable=" << WS.isVariable() <<
"\n");
1588 if (WS.isVariable())
1590 if (WS.isComdat() && !WS.isDefined())
1593 if (WS.isFunction()) {
1595 if (WS.isDefined()) {
1596 if (WS.getOffset() != 0)
1598 "function sections must contain one function each");
1601 Index = NumFunctionImports + Functions.
size();
1603 Func.SigIndex = getFunctionType(WS);
1604 Func.Section = &WS.getSection();
1605 assert(WasmIndices.count(&WS) == 0);
1606 WasmIndices[&WS] =
Index;
1611 Comdats[
C->getName()].emplace_back(
1615 if (WS.hasExportName()) {
1617 Export.Name = WS.getExportName();
1624 Index = WasmIndices.find(&WS)->second;
1629 }
else if (WS.isData()) {
1633 if (!WS.isDefined()) {
1644 if (!WS.getSize()->evaluateAsAbsolute(
Size, Asm))
1647 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1648 if (!DataSection.isWasmData())
1655 DataSection.getSegmentIndex(),
Asm.getSymbolOffset(WS),
1657 assert(DataLocations.count(&WS) == 0);
1658 DataLocations[&WS] =
Ref;
1661 }
else if (WS.isGlobal()) {
1663 if (WS.isDefined()) {
1665 Global.Type = WS.getGlobalType();
1666 Global.Index = NumGlobalImports + Globals.
size();
1667 Global.InitExpr.Extended =
false;
1668 switch (
Global.Type.Type) {
1687 assert(WasmIndices.count(&WS) == 0);
1688 WasmIndices[&WS] =
Global.Index;
1693 << WasmIndices.find(&WS)->second <<
"\n");
1695 }
else if (WS.isTable()) {
1696 if (WS.isDefined()) {
1698 Table.
Index = NumTableImports + Tables.
size();
1699 Table.
Type = WS.getTableType();
1700 assert(WasmIndices.count(&WS) == 0);
1701 WasmIndices[&WS] = Table.
Index;
1705 << WasmIndices.find(&WS)->second <<
"\n");
1706 }
else if (WS.isTag()) {
1710 if (WS.isDefined()) {
1711 Index = NumTagImports + TagTypes.
size();
1712 uint32_t SigIndex = getTagType(WS);
1713 assert(WasmIndices.count(&WS) == 0);
1714 WasmIndices[&WS] =
Index;
1718 assert(WasmIndices.count(&WS) > 0);
1720 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1733 if (!S.isVariable())
1738 const auto *BS =
Asm.getBaseSymbol(S);
1741 ": absolute addressing not supported!");
1749 if (
Base->isFunction()) {
1752 assert(WasmIndices.count(&WS) == 0);
1753 WasmIndices[&WS] = WasmIndex;
1755 }
else if (
Base->isData()) {
1756 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1763 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Asm))
1765 const WasmDataSegment &Segment =
1766 DataSegments[DataSection.getSegmentIndex()];
1770 DataSection.getSegmentIndex(),
1773 DataLocations[&WS] =
Ref;
1795 if (!WS.isExternal() && WS.isDefined())
1797 if (WS.isUndefined())
1799 if (WS.isNoStrip()) {
1801 if (isEmscripten()) {
1805 if (WS.hasImportName())
1807 if (WS.hasExportName())
1813 Info.Name = WS.getName();
1817 assert(WasmIndices.count(&WS) > 0);
1818 Info.ElementIndex = WasmIndices.find(&WS)->second;
1819 }
else if (WS.isDefined()) {
1820 assert(DataLocations.count(&WS) > 0);
1821 Info.DataRef = DataLocations.find(&WS)->second;
1823 WS.setIndex(SymbolInfos.
size());
1828 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1832 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1833 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1834 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1835 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1836 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1837 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1839 assert(Rel.Symbol->isFunction());
1841 cast<MCSymbolWasm>(
Asm.getBaseSymbol(*Rel.Symbol));
1842 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1843 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1844 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1846 <<
" to table: " << TableIndex <<
"\n");
1848 registerFunctionType(*
Base);
1852 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1853 HandleReloc(RelEntry);
1854 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1855 HandleReloc(RelEntry);
1861 if (WS.getName().starts_with(
".fini_array"))
1863 if (!WS.getName().starts_with(
".init_array"))
1865 auto IT = WS.begin();
1873 while (nextFrag !=
nullptr) {
1877 if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
1880 ".init_array section should be aligned for pointers");
1888 unsigned PrefixLength = strlen(
".init_array");
1889 if (WS.getName().size() > PrefixLength) {
1890 if (WS.getName()[PrefixLength] !=
'.')
1892 ".init_array section priority should start with '.'");
1893 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1896 const auto &DataFrag = cast<MCDataFragment>(Frag);
1902 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1905 "fixups in .init_array should be symbol references");
1906 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1909 if (!TargetSym.isFunction())
1911 InitFuncs.
push_back(std::make_pair(Priority, TargetSym.getIndex()));
1919 uint32_t CodeSectionIndex, DataSectionIndex;
1920 if (Mode != DwoMode::DwoOnly) {
1922 writeImportSection(Imports, DataSize, TableElems.
size());
1923 writeFunctionSection(Functions);
1924 writeTableSection(Tables);
1926 writeTagSection(TagTypes);
1927 writeGlobalSection(Globals);
1928 writeExportSection(Exports);
1929 const MCSymbol *IndirectFunctionTable =
1930 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1931 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1933 writeDataCountSection();
1935 CodeSectionIndex = writeCodeSection(Asm, Functions);
1936 DataSectionIndex = writeDataSection(Asm);
1941 for (
auto &Group : Comdats) {
1942 for (
auto &Entry : Group.second) {
1944 Entry.Index += SectionCount;
1948 for (
auto &CustomSection : CustomSections)
1949 writeCustomSection(CustomSection, Asm);
1951 if (Mode != DwoMode::DwoOnly) {
1952 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1954 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1955 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1957 writeCustomRelocSections();
1958 if (ProducersSection)
1959 writeCustomSection(*ProducersSection, Asm);
1960 if (TargetFeaturesSection)
1961 writeCustomSection(*TargetFeaturesSection, Asm);
1964 return W->OS.tell() - StartOffset;
1967std::unique_ptr<MCObjectWriter>
1970 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS);
1973std::unique_ptr<MCObjectWriter>
1977 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_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
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
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