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;
1028 const uint8_t ElemKind = 0;
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())
1329void WasmObjectWriter::prepareImports(
1335 MemImport.
Module =
"env";
1336 MemImport.
Field =
"__linear_memory";
1350 if (WS.isFunction()) {
1351 const auto *BS =
Asm.getBaseSymbol(S);
1354 ": absolute addressing not supported!");
1355 registerFunctionType(*cast<MCSymbolWasm>(BS));
1359 registerTagType(WS);
1361 if (WS.isTemporary())
1365 if (!WS.isDefined() && !WS.isComdat()) {
1366 if (WS.isFunction()) {
1368 Import.Module = WS.getImportModule();
1369 Import.Field = WS.getImportName();
1371 Import.SigIndex = getFunctionType(WS);
1373 assert(WasmIndices.count(&WS) == 0);
1374 WasmIndices[&WS] = NumFunctionImports++;
1375 }
else if (WS.isGlobal()) {
1380 Import.Field = WS.getImportName();
1382 Import.Module = WS.getImportModule();
1383 Import.Global = WS.getGlobalType();
1385 assert(WasmIndices.count(&WS) == 0);
1386 WasmIndices[&WS] = NumGlobalImports++;
1387 }
else if (WS.isTag()) {
1392 Import.Module = WS.getImportModule();
1393 Import.Field = WS.getImportName();
1395 Import.SigIndex = getTagType(WS);
1397 assert(WasmIndices.count(&WS) == 0);
1398 WasmIndices[&WS] = NumTagImports++;
1399 }
else if (WS.isTable()) {
1404 Import.Module = WS.getImportModule();
1405 Import.Field = WS.getImportName();
1407 Import.Table = WS.getTableType();
1409 assert(WasmIndices.count(&WS) == 0);
1410 WasmIndices[&WS] = NumTableImports++;
1418 if (WS.isUsedInGOT()) {
1420 if (WS.isFunction())
1421 Import.Module =
"GOT.func";
1423 Import.Module =
"GOT.mem";
1424 Import.Field = WS.getName();
1428 assert(GOTIndices.count(&WS) == 0);
1429 GOTIndices[&WS] = NumGlobalImports++;
1438 uint64_t TotalSize = writeOneObject(Asm, DwoMode::NonDwoOnly);
1442 return TotalSize + writeOneObject(Asm, DwoMode::DwoOnly);
1444 return writeOneObject(Asm, DwoMode::AllSections);
1452 CustomSections.clear();
1466 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1468 if (Mode != DwoMode::DwoOnly)
1469 prepareImports(Imports, Asm);
1483 <<
Section.getGroup() <<
"\n";);
1494 uint32_t SegmentIndex = DataSegments.size();
1496 DataSegments.emplace_back();
1497 WasmDataSegment &Segment = DataSegments.back();
1499 Segment.InitFlags =
Section.getPassive()
1502 Segment.Offset = DataSize;
1504 addData(Segment.Data, Section);
1506 Segment.LinkingFlags =
Section.getSegmentFlags();
1507 DataSize += Segment.Data.size();
1508 Section.setSegmentIndex(SegmentIndex);
1511 Comdats[
C->getName()].emplace_back(
1521 Name.consume_front(
".custom_section.");
1523 MCSymbol *Begin = Sec.getBeginSymbol();
1525 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1526 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1530 if (
Name ==
"producers") {
1531 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &Section);
1534 if (
Name ==
"target_features") {
1535 TargetFeaturesSection =
1536 std::make_unique<WasmCustomSection>(
Name, &Section);
1545 Comdats[
C->getName()].emplace_back(
1547 static_cast<uint32_t>(CustomSections.size())});
1550 CustomSections.emplace_back(
Name, &Section);
1554 if (Mode != DwoMode::DwoOnly) {
1559 if (S.isTemporary() && S.getName().empty())
1564 dbgs() <<
"MCSymbol: "
1567 <<
" isDefined=" << S.isDefined() <<
" isExternal="
1568 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1569 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1570 <<
" isVariable=" << WS.isVariable() <<
"\n");
1572 if (WS.isVariable())
1574 if (WS.isComdat() && !WS.isDefined())
1577 if (WS.isFunction()) {
1579 if (WS.isDefined()) {
1580 if (WS.getOffset() != 0)
1582 "function sections must contain one function each");
1585 Index = NumFunctionImports + Functions.
size();
1587 Func.SigIndex = getFunctionType(WS);
1588 Func.Section = &WS.getSection();
1589 assert(WasmIndices.count(&WS) == 0);
1590 WasmIndices[&WS] =
Index;
1595 Comdats[
C->getName()].emplace_back(
1599 if (WS.hasExportName()) {
1601 Export.Name = WS.getExportName();
1608 Index = WasmIndices.find(&WS)->second;
1613 }
else if (WS.isData()) {
1617 if (!WS.isDefined()) {
1628 if (!WS.getSize()->evaluateAsAbsolute(
Size, Asm))
1631 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1632 if (!DataSection.isWasmData())
1639 DataSection.getSegmentIndex(),
Asm.getSymbolOffset(WS),
1641 assert(DataLocations.count(&WS) == 0);
1642 DataLocations[&WS] =
Ref;
1645 }
else if (WS.isGlobal()) {
1647 if (WS.isDefined()) {
1649 Global.Type = WS.getGlobalType();
1650 Global.Index = NumGlobalImports + Globals.
size();
1651 Global.InitExpr.Extended =
false;
1652 switch (
Global.Type.Type) {
1671 assert(WasmIndices.count(&WS) == 0);
1672 WasmIndices[&WS] =
Global.Index;
1677 << WasmIndices.find(&WS)->second <<
"\n");
1679 }
else if (WS.isTable()) {
1680 if (WS.isDefined()) {
1682 Table.
Index = NumTableImports + Tables.
size();
1683 Table.
Type = WS.getTableType();
1684 assert(WasmIndices.count(&WS) == 0);
1685 WasmIndices[&WS] = Table.
Index;
1689 << WasmIndices.find(&WS)->second <<
"\n");
1690 }
else if (WS.isTag()) {
1694 if (WS.isDefined()) {
1695 Index = NumTagImports + TagTypes.
size();
1696 uint32_t SigIndex = getTagType(WS);
1697 assert(WasmIndices.count(&WS) == 0);
1698 WasmIndices[&WS] =
Index;
1702 assert(WasmIndices.count(&WS) > 0);
1704 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1717 if (!S.isVariable())
1722 const auto *BS =
Asm.getBaseSymbol(S);
1725 ": absolute addressing not supported!");
1733 if (
Base->isFunction()) {
1736 assert(WasmIndices.count(&WS) == 0);
1737 WasmIndices[&WS] = WasmIndex;
1739 }
else if (
Base->isData()) {
1740 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1747 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Asm))
1749 const WasmDataSegment &Segment =
1750 DataSegments[DataSection.getSegmentIndex()];
1754 DataSection.getSegmentIndex(),
1757 DataLocations[&WS] =
Ref;
1779 if (!WS.isExternal() && WS.isDefined())
1781 if (WS.isUndefined())
1783 if (WS.isNoStrip()) {
1785 if (isEmscripten()) {
1789 if (WS.hasImportName())
1791 if (WS.hasExportName())
1797 Info.Name = WS.getName();
1801 assert(WasmIndices.count(&WS) > 0);
1802 Info.ElementIndex = WasmIndices.find(&WS)->second;
1803 }
else if (WS.isDefined()) {
1804 assert(DataLocations.count(&WS) > 0);
1805 Info.DataRef = DataLocations.find(&WS)->second;
1807 WS.setIndex(SymbolInfos.
size());
1812 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1816 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1817 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1818 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1819 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1820 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1821 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1823 assert(Rel.Symbol->isFunction());
1825 cast<MCSymbolWasm>(
Asm.getBaseSymbol(*Rel.Symbol));
1826 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1827 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1828 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1830 <<
" to table: " << TableIndex <<
"\n");
1832 registerFunctionType(*
Base);
1836 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1837 HandleReloc(RelEntry);
1838 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1839 HandleReloc(RelEntry);
1845 if (WS.getName().starts_with(
".fini_array"))
1847 if (!WS.getName().starts_with(
".init_array"))
1849 auto IT = WS.begin();
1859 if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
1868 unsigned PrefixLength = strlen(
".init_array");
1869 if (WS.getName().size() > PrefixLength) {
1870 if (WS.getName()[PrefixLength] !=
'.')
1872 ".init_array section priority should start with '.'");
1873 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1876 const auto &DataFrag = cast<MCDataFragment>(Frag);
1878 for (
const uint8_t *
1879 P = (
const uint8_t *)Contents.
data(),
1880 *
End = (
const uint8_t *)Contents.
data() + Contents.
size();
1889 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1892 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1895 if (!TargetSym.isFunction())
1898 std::make_pair(Priority, TargetSym.getIndex()));
1905 uint32_t CodeSectionIndex, DataSectionIndex;
1906 if (Mode != DwoMode::DwoOnly) {
1908 writeImportSection(Imports, DataSize, TableElems.
size());
1909 writeFunctionSection(Functions);
1910 writeTableSection(Tables);
1912 writeTagSection(TagTypes);
1913 writeGlobalSection(Globals);
1914 writeExportSection(Exports);
1915 const MCSymbol *IndirectFunctionTable =
1916 Asm.getContext().lookupSymbol(
"__indirect_function_table");
1917 writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1919 writeDataCountSection();
1921 CodeSectionIndex = writeCodeSection(Asm, Functions);
1922 DataSectionIndex = writeDataSection(Asm);
1927 for (
auto &Group : Comdats) {
1928 for (
auto &Entry : Group.second) {
1930 Entry.Index += SectionCount;
1934 for (
auto &CustomSection : CustomSections)
1935 writeCustomSection(CustomSection, Asm);
1937 if (Mode != DwoMode::DwoOnly) {
1938 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1940 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1941 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1943 writeCustomRelocSections();
1944 if (ProducersSection)
1945 writeCustomSection(*ProducersSection, Asm);
1946 if (TargetFeaturesSection)
1947 writeCustomSection(*TargetFeaturesSection, Asm);
1950 return W->OS.tell() - StartOffset;
1953std::unique_ptr<MCObjectWriter>
1956 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS);
1959std::unique_ptr<MCObjectWriter>
1963 return std::make_unique<WasmObjectWriter>(std::move(MOTW),
OS, DwoOS);
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
PowerPC TLS Dynamic Call Fixup
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const FuncProtoTy Signatures[]
static const unsigned InvalidIndex
static void addData(SmallVectorImpl< char > &DataBytes, MCSectionWasm &DataSection)
static bool isInSymtab(const MCSymbolWasm &Sym)
static 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.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
NodeAddr< FuncNode * > Func
void write64le(void *P, uint64_t V)
void write32le(void *P, uint32_t V)
const unsigned WASM_SYMBOL_UNDEFINED
const uint32_t WasmPageSize
const unsigned WASM_SYMBOL_NO_STRIP
@ WASM_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.
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