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)) {
740 const auto &DataFrag = cast<MCDataFragment>(Frag);
750WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
751 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
752 if (!TypeIndices.count(RelEntry.Symbol))
754 RelEntry.Symbol->getName());
755 return TypeIndices[RelEntry.Symbol];
758 return RelEntry.Symbol->getIndex();
763void WasmObjectWriter::applyRelocations(
767 for (
const WasmRelocationEntry &RelEntry : Relocations) {
769 RelEntry.FixupSection->getSectionOffset() +
775 switch (RelEntry.Type) {
776 case wasm::R_WASM_FUNCTION_INDEX_LEB:
777 case wasm::R_WASM_TYPE_INDEX_LEB:
778 case wasm::R_WASM_GLOBAL_INDEX_LEB:
779 case wasm::R_WASM_MEMORY_ADDR_LEB:
780 case wasm::R_WASM_TAG_INDEX_LEB:
781 case wasm::R_WASM_TABLE_NUMBER_LEB:
784 case wasm::R_WASM_MEMORY_ADDR_LEB64:
787 case wasm::R_WASM_TABLE_INDEX_I32:
788 case wasm::R_WASM_MEMORY_ADDR_I32:
789 case wasm::R_WASM_FUNCTION_OFFSET_I32:
790 case wasm::R_WASM_FUNCTION_INDEX_I32:
791 case wasm::R_WASM_SECTION_OFFSET_I32:
792 case wasm::R_WASM_GLOBAL_INDEX_I32:
793 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
796 case wasm::R_WASM_TABLE_INDEX_I64:
797 case wasm::R_WASM_MEMORY_ADDR_I64:
798 case wasm::R_WASM_FUNCTION_OFFSET_I64:
801 case wasm::R_WASM_TABLE_INDEX_SLEB:
802 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
803 case wasm::R_WASM_MEMORY_ADDR_SLEB:
804 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
805 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
808 case wasm::R_WASM_TABLE_INDEX_SLEB64:
809 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
810 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
811 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
812 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
821void WasmObjectWriter::writeTypeSection(
857 writeString(
Import.Module);
858 writeString(
Import.Field);
891 if (Functions.
empty())
898 for (
const WasmFunction &Func : Functions)
905 if (TagTypes.
empty())
931 if (
Global.InitExpr.Extended) {
935 switch (
Global.Type.Type) {
949 writeValueType(wasm::ValType::EXTERNREF);
970 assert(Table.Type.ElemType != wasm::ValType::OTHERREF &&
971 "Cannot encode general ref-typed tables");
998void WasmObjectWriter::writeElemSection(
1000 if (TableElems.
empty())
1003 assert(IndirectFunctionTable);
1010 assert(WasmIndices.count(IndirectFunctionTable));
1011 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
1036 endSection(Section);
1039void WasmObjectWriter::writeDataCountSection() {
1040 if (DataSegments.empty())
1046 endSection(Section);
1051 if (Functions.
empty())
1059 for (
const WasmFunction &Func : Functions) {
1062 int64_t
Size =
Asm.getSectionAddressSize(*FuncSection);
1064 FuncSection->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1065 Asm.writeSectionData(
W->OS, FuncSection);
1069 applyRelocations(CodeRelocations,
Section.ContentsOffset, Asm);
1071 endSection(Section);
1076 if (DataSegments.empty())
1084 for (
const WasmDataSegment &Segment : DataSegments) {
1095 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1096 W->OS << Segment.Data;
1100 applyRelocations(DataRelocations,
Section.ContentsOffset, Asm);
1102 endSection(Section);
1106void WasmObjectWriter::writeRelocSection(
1108 std::vector<WasmRelocationEntry> &Relocs) {
1121 Relocs, [](
const WasmRelocationEntry &
A,
const WasmRelocationEntry &
B) {
1122 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1123 (
B.Offset +
B.FixupSection->getSectionOffset());
1127 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1131 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1133 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1136 W->OS <<
char(RelEntry.Type);
1139 if (RelEntry.hasAddend())
1143 endSection(Section);
1146void WasmObjectWriter::writeCustomRelocSections() {
1147 for (
const auto &Sec : CustomSections) {
1148 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1149 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1153void WasmObjectWriter::writeLinkingMetaDataSection(
1155 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1156 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1158 startCustomSection(Section,
"linking");
1161 SectionBookkeeping SubSection;
1162 if (SymbolInfos.
size() != 0) {
1176 writeString(
Sym.Name);
1179 writeString(
Sym.Name);
1188 CustomSections[
Sym.ElementIndex].OutputIndex;
1196 endSection(SubSection);
1199 if (DataSegments.size()) {
1202 for (
const WasmDataSegment &Segment : DataSegments) {
1203 writeString(Segment.Name);
1207 endSection(SubSection);
1210 if (!InitFuncs.empty()) {
1213 for (
auto &StartFunc : InitFuncs) {
1217 endSection(SubSection);
1220 if (Comdats.size()) {
1223 for (
const auto &
C : Comdats) {
1224 writeString(
C.first);
1227 for (
const WasmComdatEntry &Entry :
C.second) {
1232 endSection(SubSection);
1235 endSection(Section);
1238void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1241 auto *Sec = CustomSection.Section;
1242 startCustomSection(Section, CustomSection.Name);
1244 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1245 Asm.writeSectionData(
W->OS, Sec);
1247 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1248 CustomSection.OutputIndex =
Section.Index;
1250 endSection(Section);
1253 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1254 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Asm);
1259 assert(TypeIndices.count(&Symbol));
1260 return TypeIndices[&
Symbol];
1265 assert(TypeIndices.count(&Symbol));
1266 return TypeIndices[&
Symbol];
1269void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1274 if (
auto *Sig =
Symbol.getSignature()) {
1282 TypeIndices[&
Symbol] = Pair.first->second;
1285 <<
" new:" << Pair.second <<
"\n");
1286 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1289void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1295 if (
auto *Sig =
Symbol.getSignature()) {
1303 TypeIndices[&
Symbol] = Pair.first->second;
1305 LLVM_DEBUG(
dbgs() <<
"registerTagType: " << Symbol <<
" new:" << Pair.second
1307 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1311 if (
Sym.isUsedInReloc() ||
Sym.isUsedInInitArray())
1314 if (
Sym.isComdat() && !
Sym.isDefined())
1317 if (
Sym.isTemporary())
1320 if (
Sym.isSection())
1323 if (
Sym.omitFromLinkingSection())
1332 for (
const MCSymbol &S : Asm.symbols()) {
1334 if (WS.isData() && WS.isInSection()) {
1335 auto &RefSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1345void WasmObjectWriter::prepareImports(
1351 MemImport.
Module =
"env";
1352 MemImport.
Field =
"__linear_memory";
1366 if (WS.isFunction()) {
1367 const auto *BS =
Asm.getBaseSymbol(S);
1370 ": absolute addressing not supported!");
1371 registerFunctionType(*cast<MCSymbolWasm>(BS));
1375 registerTagType(WS);
1377 if (WS.isTemporary())
1381 if (!WS.isDefined() && !WS.isComdat()) {
1382 if (WS.isFunction()) {
1384 Import.Module = WS.getImportModule();
1385 Import.Field = WS.getImportName();
1387 Import.SigIndex = getFunctionType(WS);
1389 assert(WasmIndices.count(&WS) == 0);
1390 WasmIndices[&WS] = NumFunctionImports++;
1391 }
else if (WS.isGlobal()) {
1396 Import.Field = WS.getImportName();
1398 Import.Module = WS.getImportModule();
1399 Import.Global = WS.getGlobalType();
1401 assert(WasmIndices.count(&WS) == 0);
1402 WasmIndices[&WS] = NumGlobalImports++;
1403 }
else if (WS.isTag()) {
1408 Import.Module = WS.getImportModule();
1409 Import.Field = WS.getImportName();
1411 Import.SigIndex = getTagType(WS);
1413 assert(WasmIndices.count(&WS) == 0);
1414 WasmIndices[&WS] = NumTagImports++;
1415 }
else if (WS.isTable()) {
1420 Import.Module = WS.getImportModule();
1421 Import.Field = WS.getImportName();
1423 Import.Table = WS.getTableType();
1425 assert(WasmIndices.count(&WS) == 0);
1426 WasmIndices[&WS] = NumTableImports++;
1434 if (WS.isUsedInGOT()) {
1436 if (WS.isFunction())
1437 Import.Module =
"GOT.func";
1439 Import.Module =
"GOT.mem";
1440 Import.Field = WS.getName();
1444 assert(GOTIndices.count(&WS) == 0);
1445 GOTIndices[&WS] = NumGlobalImports++;
1454 uint64_t TotalSize = writeOneObject(Asm, DwoMode::NonDwoOnly);
1458 return TotalSize + writeOneObject(Asm, DwoMode::DwoOnly);
1460 return writeOneObject(Asm, DwoMode::AllSections);
1468 CustomSections.clear();
1482 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1484 if (Mode != DwoMode::DwoOnly)
1485 prepareImports(Imports, Asm);
1499 <<
Section.getGroup() <<
"\n";);
1512 uint32_t SegmentIndex = DataSegments.size();
1514 DataSegments.emplace_back();
1515 WasmDataSegment &Segment = DataSegments.back();
1517 Segment.InitFlags =
Section.getPassive()
1520 Segment.Offset = DataSize;
1522 addData(Segment.Data, Section);
1524 Segment.LinkingFlags =
Section.getSegmentFlags();
1525 DataSize += Segment.Data.size();
1526 Section.setSegmentIndex(SegmentIndex);
1529 Comdats[
C->getName()].emplace_back(
1539 Name.consume_front(
".custom_section.");
1541 MCSymbol *Begin = Sec.getBeginSymbol();
1543 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1544 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1548 if (
Name ==
"producers") {
1549 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &Section);
1552 if (
Name ==
"target_features") {
1553 TargetFeaturesSection =
1554 std::make_unique<WasmCustomSection>(
Name, &Section);
1563 Comdats[
C->getName()].emplace_back(
1565 static_cast<uint32_t>(CustomSections.size())});
1568 CustomSections.emplace_back(
Name, &Section);
1572 if (Mode != DwoMode::DwoOnly) {
1577 if (S.isTemporary() && S.getName().empty())
1582 dbgs() <<
"MCSymbol: "
1585 <<
" isDefined=" << S.isDefined() <<
" isExternal="
1586 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1587 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1588 <<
" isVariable=" << WS.isVariable() <<
"\n");
1590 if (WS.isVariable())
1592 if (WS.isComdat() && !WS.isDefined())
1595 if (WS.isFunction()) {
1597 if (WS.isDefined()) {
1598 if (WS.getOffset() != 0)
1600 "function sections must contain one function each");
1603 Index = NumFunctionImports + Functions.
size();
1605 Func.SigIndex = getFunctionType(WS);
1606 Func.Section = &WS.getSection();
1607 assert(WasmIndices.count(&WS) == 0);
1608 WasmIndices[&WS] =
Index;
1613 Comdats[
C->getName()].emplace_back(
1617 if (WS.hasExportName()) {
1619 Export.Name = WS.getExportName();
1626 Index = WasmIndices.find(&WS)->second;
1631 }
else if (WS.isData()) {
1635 if (!WS.isDefined()) {
1646 if (!WS.getSize()->evaluateAsAbsolute(
Size, Asm))
1649 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1650 if (!DataSection.isWasmData())
1657 DataSection.getSegmentIndex(),
Asm.getSymbolOffset(WS),
1659 assert(DataLocations.count(&WS) == 0);
1660 DataLocations[&WS] =
Ref;
1663 }
else if (WS.isGlobal()) {
1665 if (WS.isDefined()) {
1667 Global.Type = WS.getGlobalType();
1668 Global.Index = NumGlobalImports + Globals.
size();
1669 Global.InitExpr.Extended =
false;
1670 switch (
Global.Type.Type) {
1689 assert(WasmIndices.count(&WS) == 0);
1690 WasmIndices[&WS] =
Global.Index;
1695 << WasmIndices.find(&WS)->second <<
"\n");
1697 }
else if (WS.isTable()) {
1698 if (WS.isDefined()) {
1700 Table.
Index = NumTableImports + Tables.
size();
1701 Table.
Type = WS.getTableType();
1702 assert(WasmIndices.count(&WS) == 0);
1703 WasmIndices[&WS] = Table.
Index;
1707 << WasmIndices.find(&WS)->second <<
"\n");
1708 }
else if (WS.isTag()) {
1712 if (WS.isDefined()) {
1713 Index = NumTagImports + TagTypes.
size();
1714 uint32_t SigIndex = getTagType(WS);
1715 assert(WasmIndices.count(&WS) == 0);
1716 WasmIndices[&WS] =
Index;
1720 assert(WasmIndices.count(&WS) > 0);
1722 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1735 if (!S.isVariable())
1740 const auto *BS =
Asm.getBaseSymbol(S);
1743 ": absolute addressing not supported!");
1751 if (
Base->isFunction()) {
1754 assert(WasmIndices.count(&WS) == 0);
1755 WasmIndices[&WS] = WasmIndex;
1757 }
else if (
Base->isData()) {
1758 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1765 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Asm))
1767 const WasmDataSegment &Segment =
1768 DataSegments[DataSection.getSegmentIndex()];
1772 DataSection.getSegmentIndex(),
1775 DataLocations[&WS] =
Ref;
1797 if (!WS.isExternal() && WS.isDefined())
1799 if (WS.isUndefined())
1801 if (WS.isNoStrip()) {
1803 if (isEmscripten()) {
1807 if (WS.hasImportName())
1809 if (WS.hasExportName())
1815 Info.Name = WS.getName();
1819 assert(WasmIndices.count(&WS) > 0);
1820 Info.ElementIndex = WasmIndices.find(&WS)->second;
1821 }
else if (WS.isDefined()) {
1822 assert(DataLocations.count(&WS) > 0);
1823 Info.DataRef = DataLocations.find(&WS)->second;
1825 WS.setIndex(SymbolInfos.
size());
1830 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1834 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1835 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1836 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1837 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1838 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1839 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1841 assert(Rel.Symbol->isFunction());
1843 cast<MCSymbolWasm>(
Asm.getBaseSymbol(*Rel.Symbol));
1844 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1845 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1846 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1848 <<
" to table: " << TableIndex <<
"\n");
1850 registerFunctionType(*
Base);
1854 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1855 HandleReloc(RelEntry);
1856 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1857 HandleReloc(RelEntry);
1863 if (WS.getName().starts_with(
".fini_array"))
1865 if (!WS.getName().starts_with(
".init_array"))
1867 auto IT = WS.begin();
1875 while (nextFrag !=
nullptr) {
1879 if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
1882 ".init_array section should be aligned for pointers");
1890 unsigned PrefixLength = strlen(
".init_array");
1891 if (WS.getName().size() > PrefixLength) {
1892 if (WS.getName()[PrefixLength] !=
'.')
1894 ".init_array section priority should start with '.'");
1895 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1898 const auto &DataFrag = cast<MCDataFragment>(Frag);
1911 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1914 "fixups in .init_array should be symbol references");
1915 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1918 if (!TargetSym.isFunction())
1920 InitFuncs.
push_back(std::make_pair(Priority, TargetSym.getIndex()));
1928 uint32_t CodeSectionIndex, DataSectionIndex;
1929 if (Mode != DwoMode::DwoOnly) {
1931 writeImportSection(Imports, DataSize, TableElems.
size());
1932 writeFunctionSection(Functions);
1933 writeTableSection(Tables);
1935 writeTagSection(TagTypes);
1936 writeGlobalSection(Globals);
1937 writeExportSection(Exports);
1938 const MCSymbol *IndirectFunctionTable =
1939 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1940 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1942 writeDataCountSection();
1944 CodeSectionIndex = writeCodeSection(Asm, Functions);
1945 DataSectionIndex = writeDataSection(Asm);
1950 for (
auto &Group : Comdats) {
1951 for (
auto &Entry : Group.second) {
1953 Entry.Index += SectionCount;
1957 for (
auto &CustomSection : CustomSections)
1958 writeCustomSection(CustomSection, Asm);
1960 if (Mode != DwoMode::DwoOnly) {
1961 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1963 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1964 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1966 writeCustomRelocSections();
1967 if (ProducersSection)
1968 writeCustomSection(*ProducersSection, Asm);
1969 if (TargetFeaturesSection)
1970 writeCustomSection(*TargetFeaturesSection, Asm);
1973 return W->OS.tell() - StartOffset;
1976std::unique_ptr<MCObjectWriter>
1979 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS);
1982std::unique_ptr<MCObjectWriter>
1986 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)
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.
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)
@ 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