17 #include "llvm/Config/llvm-config.h" 39 #define DEBUG_TYPE "mc" 45 static const uint32_t InitialTableOffset = 1;
50 struct SectionBookkeeping {
54 uint64_t PayloadOffset;
56 uint64_t ContentsOffset;
64 struct WasmDataSegment {
83 uint64_t InitialValue;
89 struct WasmComdatEntry {
95 struct WasmRelocationEntry {
103 int64_t Addend,
unsigned Type,
106 FixupSection(FixupSection) {}
112 <<
", Sym=" << *
Symbol <<
", Addend=" << Addend
113 <<
", FixupSection=" << FixupSection->
getName();
116 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 123 struct WasmCustomSection {
176 bool isDwoSection(
const MCSection &Sec) {
184 std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
187 std::vector<WasmRelocationEntry> CodeRelocations;
189 std::vector<WasmRelocationEntry> DataRelocations;
206 std::vector<WasmCustomSection> CustomSections;
207 std::unique_ptr<WasmCustomSection> ProducersSection;
208 std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
211 CustomSectionsRelocations;
219 unsigned NumFunctionImports = 0;
220 unsigned NumGlobalImports = 0;
221 unsigned NumTableImports = 0;
222 unsigned NumEventImports = 0;
230 bool IsSplitDwarf =
false;
235 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
236 bool isEmscripten()
const {
return TargetObjectWriter->isEmscripten(); }
238 void startSection(SectionBookkeeping &
Section,
unsigned SectionId);
240 void endSection(SectionBookkeeping &
Section);
243 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
245 : TargetObjectWriter(
std::move(MOTW)), OS(&OS_) {}
247 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
249 : TargetObjectWriter(
std::move(MOTW)), IsSplitDwarf(
true), OS(&OS_),
253 void reset()
override {
254 CodeRelocations.clear();
255 DataRelocations.clear();
259 TableIndices.
clear();
260 DataLocations.
clear();
261 CustomSections.clear();
262 ProducersSection.reset();
263 TargetFeaturesSection.reset();
264 CustomSectionsRelocations.
clear();
265 SignatureIndices.
clear();
267 DataSegments.
clear();
268 SectionFunctions.
clear();
269 NumFunctionImports = 0;
270 NumGlobalImports = 0;
295 void writeI32(int32_t val) {
298 W->OS.write(Buffer,
sizeof(Buffer));
301 void writeI64(int64_t val) {
304 W->OS.write(Buffer,
sizeof(Buffer));
307 void writeValueType(
wasm::ValType Ty) {
W->OS << static_cast<char>(Ty); }
315 void writeDataCountSection();
323 std::vector<WasmRelocationEntry> &Relocations);
324 void writeLinkingMetaDataSection(
326 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
327 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats);
328 void writeCustomSection(WasmCustomSection &CustomSection,
330 void writeCustomRelocSections();
332 uint64_t getProvisionalValue(
const WasmRelocationEntry &RelEntry,
335 uint64_t ContentsOffset,
const MCAsmLayout &Layout);
337 uint32_t getRelocationIndexValue(
const WasmRelocationEntry &RelEntry);
347 void WasmObjectWriter::startSection(SectionBookkeeping &
Section,
348 unsigned SectionId) {
350 W->OS <<
char(SectionId);
359 Section.ContentsOffset =
W->OS.tell();
360 Section.PayloadOffset =
W->OS.tell();
361 Section.Index = SectionCount++;
364 void WasmObjectWriter::startCustomSection(SectionBookkeeping &
Section,
370 Section.PayloadOffset =
W->OS.tell();
376 Section.ContentsOffset =
W->OS.tell();
381 void WasmObjectWriter::endSection(SectionBookkeeping &
Section) {
382 uint64_t
Size =
W->OS.tell();
396 writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(
W->OS),
Size,
412 if (
auto *Sym =
Asm.getContext().lookupSymbol(
"__indirect_function_table"))
413 Asm.registerSymbol(*Sym);
418 const auto &WS = static_cast<const MCSymbolWasm &>(S);
419 if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
420 const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());
421 auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
433 uint64_t &FixedValue) {
435 assert(!(
Asm.getBackend().getFixupKindInfo(
Fixup.getKind()).Flags &
438 const auto &FixupSection = cast<MCSectionWasm>(*Fragment->
getParent());
439 uint64_t
C =
Target.getConstant();
447 const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
450 Twine(
"symbol '") + SymB.getName() +
451 "': unsupported subtraction expression used in relocation.");
457 const auto *SymA = cast<MCSymbolWasm>(&RefA->
getSymbol());
460 if (FixupSection.getName().startswith(
".init_array")) {
461 SymA->setUsedInInitArray();
465 if (SymA->isVariable()) {
466 const MCExpr *Expr = SymA->getVariableValue();
467 if (
const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr))
477 unsigned Type = TargetObjectWriter->getRelocType(
Target, Fixup);
482 if (
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
483 Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
484 Type == wasm::R_WASM_SECTION_OFFSET_I32) {
485 if (!FixupSection.getKind().isMetadata())
487 "only supported in metadata sections");
489 const MCSymbol *SectionSymbol =
nullptr;
490 const MCSection &SecA = SymA->getSection();
492 SectionSymbol = SectionFunctions.find(&SecA)->second;
499 SymA = cast<MCSymbolWasm>(SectionSymbol);
502 if (
Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
503 Type == wasm::R_WASM_TABLE_INDEX_SLEB ||
504 Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||
505 Type == wasm::R_WASM_TABLE_INDEX_I32 ||
506 Type == wasm::R_WASM_TABLE_INDEX_I64) {
508 auto TableName =
"__indirect_function_table";
514 "symbol '__indirect_function_table' is not a function table");
522 Asm.registerSymbol(*Sym);
527 if (
Type != wasm::R_WASM_TYPE_INDEX_LEB) {
528 if (SymA->getName().empty())
530 "supported by wasm");
532 SymA->setUsedInReloc();
536 SymA->setUsedInGOT();
538 WasmRelocationEntry Rec(FixupOffset, SymA,
C,
Type, &FixupSection);
541 if (FixupSection.isWasmData()) {
542 DataRelocations.push_back(Rec);
543 }
else if (FixupSection.getKind().isText()) {
544 CodeRelocations.push_back(Rec);
545 }
else if (FixupSection.getKind().isMetadata()) {
546 CustomSectionsRelocations[&FixupSection].push_back(Rec);
557 WasmObjectWriter::getProvisionalValue(
const WasmRelocationEntry &RelEntry,
559 if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
560 RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
561 !RelEntry.Symbol->isGlobal()) {
562 assert(GOTIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in GOT index space");
563 return GOTIndices[RelEntry.Symbol];
566 switch (RelEntry.Type) {
567 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
568 case wasm::R_WASM_TABLE_INDEX_SLEB:
569 case wasm::R_WASM_TABLE_INDEX_SLEB64:
570 case wasm::R_WASM_TABLE_INDEX_I32:
571 case wasm::R_WASM_TABLE_INDEX_I64: {
576 if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB)
577 return TableIndices[
Base] - InitialTableOffset;
579 return TableIndices[
Base];
581 case wasm::R_WASM_TYPE_INDEX_LEB:
583 return getRelocationIndexValue(RelEntry);
584 case wasm::R_WASM_FUNCTION_INDEX_LEB:
585 case wasm::R_WASM_GLOBAL_INDEX_LEB:
586 case wasm::R_WASM_GLOBAL_INDEX_I32:
587 case wasm::R_WASM_EVENT_INDEX_LEB:
588 case wasm::R_WASM_TABLE_NUMBER_LEB:
590 assert(WasmIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in wasm index space");
591 return WasmIndices[RelEntry.Symbol];
592 case wasm::R_WASM_FUNCTION_OFFSET_I32:
593 case wasm::R_WASM_FUNCTION_OFFSET_I64:
594 case wasm::R_WASM_SECTION_OFFSET_I32: {
596 static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
597 return Section.getSectionOffset() + RelEntry.Addend;
599 case wasm::R_WASM_MEMORY_ADDR_LEB:
600 case wasm::R_WASM_MEMORY_ADDR_LEB64:
601 case wasm::R_WASM_MEMORY_ADDR_SLEB:
602 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
603 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
604 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
605 case wasm::R_WASM_MEMORY_ADDR_I32:
606 case wasm::R_WASM_MEMORY_ADDR_I64:
607 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: {
612 if (!
Base->isDefined())
615 &SymRef = DataLocations[RelEntry.Symbol];
616 const WasmDataSegment &Segment = DataSegments[BaseRef.
Segment];
618 return Segment.Offset + BaseRef.
Offset + SymRef.Offset + RelEntry.Addend;
632 if (Frag.hasInstructions())
635 if (
auto *
Align = dyn_cast<MCAlignFragment>(&Frag)) {
636 if (
Align->getValueSize() != 1)
642 DataBytes.
size() +
Align->getMaxBytesToEmit());
644 }
else if (
auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
646 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
648 DataBytes.
insert(DataBytes.
end(), Fill->getValueSize() * NumValues,
650 }
else if (
auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
654 const auto &DataFrag = cast<MCDataFragment>(Frag);
664 WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
665 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
666 if (!TypeIndices.count(RelEntry.Symbol))
668 RelEntry.Symbol->getName());
669 return TypeIndices[RelEntry.Symbol];
672 return RelEntry.Symbol->getIndex();
677 void WasmObjectWriter::applyRelocations(
680 auto &Stream = static_cast<raw_pwrite_stream &>(
W->OS);
681 for (
const WasmRelocationEntry &RelEntry : Relocations) {
682 uint64_t
Offset = ContentsOffset +
683 RelEntry.FixupSection->getSectionOffset() +
687 auto Value = getProvisionalValue(RelEntry, Layout);
689 switch (RelEntry.Type) {
690 case wasm::R_WASM_FUNCTION_INDEX_LEB:
691 case wasm::R_WASM_TYPE_INDEX_LEB:
692 case wasm::R_WASM_GLOBAL_INDEX_LEB:
693 case wasm::R_WASM_MEMORY_ADDR_LEB:
694 case wasm::R_WASM_EVENT_INDEX_LEB:
695 case wasm::R_WASM_TABLE_NUMBER_LEB:
698 case wasm::R_WASM_MEMORY_ADDR_LEB64:
701 case wasm::R_WASM_TABLE_INDEX_I32:
702 case wasm::R_WASM_MEMORY_ADDR_I32:
703 case wasm::R_WASM_FUNCTION_OFFSET_I32:
704 case wasm::R_WASM_SECTION_OFFSET_I32:
705 case wasm::R_WASM_GLOBAL_INDEX_I32:
708 case wasm::R_WASM_TABLE_INDEX_I64:
709 case wasm::R_WASM_MEMORY_ADDR_I64:
710 case wasm::R_WASM_FUNCTION_OFFSET_I64:
713 case wasm::R_WASM_TABLE_INDEX_SLEB:
714 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
715 case wasm::R_WASM_MEMORY_ADDR_SLEB:
716 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
717 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
720 case wasm::R_WASM_TABLE_INDEX_SLEB64:
721 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
722 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
731 void WasmObjectWriter::writeTypeSection(
733 if (Signatures.
empty())
767 writeString(
Import.Module);
768 writeString(
Import.Field);
801 if (Functions.
empty())
808 for (
const WasmFunction &Func : Functions)
842 switch (
Global.Type.Type) {
903 if (TableElems.
empty())
924 void WasmObjectWriter::writeDataCountSection() {
925 if (DataSegments.empty())
937 if (Functions.
empty())
945 for (
const WasmFunction &Func : Functions) {
946 auto &FuncSection = static_cast<MCSectionWasm &>(
Func.Sym->getSection());
949 if (!
Func.Sym->getSize()->evaluateAsAbsolute(
Size, Layout))
953 FuncSection.setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
954 Asm.writeSectionData(
W->OS, &FuncSection, Layout);
958 applyRelocations(CodeRelocations,
Section.ContentsOffset, Layout);
965 if (DataSegments.empty())
973 for (
const WasmDataSegment &Segment : DataSegments) {
984 Segment.Section->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
985 W->OS << Segment.Data;
989 applyRelocations(DataRelocations,
Section.ContentsOffset, Layout);
995 void WasmObjectWriter::writeRelocSection(
997 std::vector<WasmRelocationEntry> &Relocs) {
1010 Relocs, [](
const WasmRelocationEntry &A,
const WasmRelocationEntry &
B) {
1011 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1012 (
B.Offset +
B.FixupSection->getSectionOffset());
1016 startCustomSection(
Section, std::string(
"reloc.") +
Name.str());
1020 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1022 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1025 W->OS <<
char(RelEntry.Type);
1028 if (RelEntry.hasAddend())
1035 void WasmObjectWriter::writeCustomRelocSections() {
1036 for (
const auto &Sec : CustomSections) {
1037 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1038 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1042 void WasmObjectWriter::writeLinkingMetaDataSection(
1044 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1045 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1047 startCustomSection(
Section,
"linking");
1050 SectionBookkeeping SubSection;
1051 if (SymbolInfos.
size() != 0) {
1065 writeString(Sym.Name);
1068 writeString(Sym.Name);
1077 CustomSections[Sym.ElementIndex].OutputIndex;
1085 endSection(SubSection);
1088 if (DataSegments.size()) {
1091 for (
const WasmDataSegment &Segment : DataSegments) {
1092 writeString(Segment.Name);
1096 endSection(SubSection);
1099 if (!InitFuncs.empty()) {
1102 for (
auto &StartFunc : InitFuncs) {
1106 endSection(SubSection);
1109 if (Comdats.size()) {
1112 for (
const auto &
C : Comdats) {
1113 writeString(
C.first);
1116 for (
const WasmComdatEntry &Entry :
C.second) {
1121 endSection(SubSection);
1127 void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1131 auto *Sec = CustomSection.Section;
1132 startCustomSection(
Section, CustomSection.Name);
1134 Sec->setSectionOffset(
W->OS.tell() -
Section.ContentsOffset);
1135 Asm.writeSectionData(
W->OS, Sec, Layout);
1137 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1138 CustomSection.OutputIndex =
Section.Index;
1143 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1144 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
1150 return TypeIndices[&
Symbol];
1156 return TypeIndices[&
Symbol];
1164 if (
auto *Sig =
Symbol.getSignature()) {
1166 S.Params = Sig->Params;
1169 auto Pair = SignatureIndices.
insert(std::make_pair(S, Signatures.size()));
1171 Signatures.push_back(S);
1172 TypeIndices[&
Symbol] = Pair.first->second;
1175 <<
" new:" << Pair.second <<
"\n");
1176 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1185 if (
auto *Sig =
Symbol.getSignature()) {
1187 S.Params = Sig->Params;
1190 auto Pair = SignatureIndices.
insert(std::make_pair(S, Signatures.size()));
1192 Signatures.push_back(S);
1193 TypeIndices[&
Symbol] = Pair.first->second;
1197 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1216 void WasmObjectWriter::prepareImports(
1223 MemImport.
Module =
"env";
1224 MemImport.
Field =
"__linear_memory";
1234 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1238 if (WS.isFunction()) {
1242 ": absolute addressing not supported!");
1243 registerFunctionType(*cast<MCSymbolWasm>(BS));
1247 registerEventType(WS);
1249 if (WS.isTemporary())
1253 if (!WS.isDefined() && !WS.isComdat()) {
1254 if (WS.isFunction()) {
1256 Import.Module = WS.getImportModule();
1257 Import.Field = WS.getImportName();
1259 Import.SigIndex = getFunctionType(WS);
1261 assert(WasmIndices.count(&WS) == 0);
1262 WasmIndices[&WS] = NumFunctionImports++;
1263 }
else if (WS.isGlobal()) {
1268 Import.Field = WS.getImportName();
1270 Import.Module = WS.getImportModule();
1271 Import.Global = WS.getGlobalType();
1273 assert(WasmIndices.count(&WS) == 0);
1274 WasmIndices[&WS] = NumGlobalImports++;
1275 }
else if (WS.isEvent()) {
1280 Import.Module = WS.getImportModule();
1281 Import.Field = WS.getImportName();
1284 Import.Event.SigIndex = getEventType(WS);
1286 assert(WasmIndices.count(&WS) == 0);
1287 WasmIndices[&WS] = NumEventImports++;
1288 }
else if (WS.isTable()) {
1293 Import.Module = WS.getImportModule();
1294 Import.Field = WS.getImportName();
1297 Import.Table.ElemType = uint8_t(ElemType);
1303 assert(WasmIndices.count(&WS) == 0);
1304 WasmIndices[&WS] = NumTableImports++;
1311 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1312 if (WS.isUsedInGOT()) {
1314 if (WS.isFunction())
1315 Import.Module =
"GOT.func";
1317 Import.Module =
"GOT.mem";
1318 Import.Field = WS.getName();
1322 assert(GOTIndices.count(&WS) == 0);
1323 GOTIndices[&WS] = NumGlobalImports++;
1333 uint64_t TotalSize = writeOneObject(
Asm, Layout, DwoMode::NonDwoOnly);
1337 return TotalSize + writeOneObject(
Asm, Layout, DwoMode::DwoOnly);
1339 return writeOneObject(
Asm, Layout, DwoMode::AllSections);
1346 uint64_t StartOffset =
W->OS.tell();
1348 CustomSections.clear();
1362 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1363 uint64_t DataSize = 0;
1364 if (
Mode != DwoMode::DwoOnly) {
1365 prepareImports(Imports,
Asm, Layout);
1371 auto &
Section = static_cast<MCSectionWasm &>(Sec);
1374 if (
Mode == DwoMode::NonDwoOnly && isDwoSection(Sec))
1376 if (
Mode == DwoMode::DwoOnly && !isDwoSection(Sec))
1380 <<
Section.getGroup() <<
"\n";);
1387 if (
Section.getKind().isText())
1391 uint32_t SegmentIndex = DataSegments.size();
1393 DataSegments.emplace_back();
1394 WasmDataSegment &Segment = DataSegments.back();
1398 Segment.Offset = DataSize;
1402 Segment.LinkerFlags = 0;
1403 DataSize += Segment.Data.size();
1404 Section.setSegmentIndex(SegmentIndex);
1407 Comdats[
C->
getName()].emplace_back(
1412 assert(Sec.getKind().isMetadata());
1417 if (
Name.startswith(
".custom_section."))
1418 Name =
Name.substr(strlen(
".custom_section."));
1420 MCSymbol *Begin = Sec.getBeginSymbol();
1422 assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1423 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1427 if (
Name ==
"producers") {
1428 ProducersSection = std::make_unique<WasmCustomSection>(
Name, &
Section);
1431 if (
Name ==
"target_features") {
1432 TargetFeaturesSection =
1433 std::make_unique<WasmCustomSection>(
Name, &
Section);
1442 Comdats[
C->
getName()].emplace_back(
1444 static_cast<uint32_t>(CustomSections.size())});
1451 if (
Mode != DwoMode::DwoOnly) {
1456 if (S.isTemporary() && S.getName().empty())
1459 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1461 dbgs() <<
"MCSymbol: " <<
toString(WS.getType()) <<
" '" << S <<
"'" 1462 <<
" isDefined=" << S.isDefined() <<
" isExternal=" 1463 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1464 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1465 <<
" isVariable=" << WS.isVariable() <<
"\n");
1467 if (WS.isVariable())
1469 if (WS.isComdat() && !WS.isDefined())
1472 if (WS.isFunction()) {
1474 if (WS.isDefined()) {
1475 if (WS.getOffset() != 0)
1477 "function sections must contain one function each");
1479 if (WS.getSize() ==
nullptr)
1481 "function symbols must have a size set with .size");
1484 Index = NumFunctionImports + Functions.
size();
1486 Func.SigIndex = getFunctionType(WS);
1488 assert(WasmIndices.count(&WS) == 0);
1489 WasmIndices[&WS] =
Index;
1492 auto &
Section = static_cast<MCSectionWasm &>(WS.getSection());
1494 Comdats[
C->
getName()].emplace_back(
1498 if (WS.hasExportName()) {
1500 Export.Name = WS.getExportName();
1507 Index = WasmIndices.find(&WS)->second;
1512 }
else if (WS.isData()) {
1516 if (!WS.isDefined()) {
1527 if (!WS.getSize()->evaluateAsAbsolute(
Size, Layout))
1530 auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1531 if (!DataSection.isWasmData())
1539 static_cast<uint64_t>(
Size)};
1540 assert(DataLocations.count(&WS) == 0);
1541 DataLocations[&WS] =
Ref;
1544 }
else if (WS.isGlobal()) {
1546 if (WS.isDefined()) {
1548 Global.Type = WS.getGlobalType();
1549 Global.Index = NumGlobalImports + Globals.
size();
1550 switch (
Global.Type.Type) {
1569 assert(WasmIndices.count(&WS) == 0);
1570 WasmIndices[&WS] =
Global.Index;
1575 << WasmIndices.find(&WS)->second <<
"\n");
1577 }
else if (WS.isTable()) {
1578 if (WS.isDefined()) {
1580 Table.
Index = NumTableImports + Tables.
size();
1581 Table.
Type.
ElemType = static_cast<uint8_t>(WS.getTableType());
1584 assert(WasmIndices.count(&WS) == 0);
1585 WasmIndices[&WS] = Table.
Index;
1589 << WasmIndices.find(&WS)->second <<
"\n");
1590 }
else if (WS.isEvent()) {
1593 if (WS.isDefined()) {
1594 Index = NumEventImports + Events.
size();
1598 assert(WasmIndices.count(&WS) == 0);
1599 WasmIndices[&WS] =
Index;
1603 assert(WasmIndices.count(&WS) > 0);
1606 << WasmIndices.find(&WS)->second <<
"\n");
1618 if (!S.isVariable())
1626 ": absolute addressing not supported!");
1630 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1634 if (
Base->isFunction()) {
1637 assert(WasmIndices.count(&WS) == 0);
1638 WasmIndices[&WS] = WasmIndex;
1640 }
else if (
Base->isData()) {
1641 auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1648 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Layout))
1650 const WasmDataSegment &Segment =
1651 DataSegments[DataSection.getSegmentIndex()];
1655 DataSection.getSegmentIndex(),
1657 static_cast<uint32_t>(
Size)};
1658 DataLocations[&WS] =
Ref;
1668 const auto &WS = static_cast<const MCSymbolWasm &>(S);
1673 if (WS.isTable() && WS.getName() ==
"__indirect_function_table") {
1684 if (!WS.isExternal() && WS.isDefined())
1686 if (WS.isUndefined())
1688 if (WS.isNoStrip()) {
1690 if (isEmscripten()) {
1694 if (WS.hasImportName())
1696 if (WS.hasExportName())
1700 Info.Name = WS.getName();
1701 Info.Kind = WS.getType();
1704 assert(WasmIndices.count(&WS) > 0);
1705 Info.ElementIndex = WasmIndices.find(&WS)->second;
1706 }
else if (WS.isDefined()) {
1707 assert(DataLocations.count(&WS) > 0);
1708 Info.DataRef = DataLocations.find(&WS)->second;
1710 WS.setIndex(SymbolInfos.
size());
1715 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1719 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1720 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1721 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1722 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1723 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB)
1725 assert(Rel.Symbol->isFunction());
1728 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1729 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1730 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1732 <<
" to table: " << TableIndex <<
"\n");
1734 registerFunctionType(*
Base);
1738 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1739 HandleReloc(RelEntry);
1740 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1741 HandleReloc(RelEntry);
1746 const auto &WS = static_cast<const MCSectionWasm &>(S);
1747 if (WS.getName().startswith(
".fini_array"))
1749 if (!WS.getName().startswith(
".init_array"))
1751 if (WS.getFragmentList().empty())
1755 if (WS.getFragmentList().size() != 3)
1758 auto IT = WS.begin();
1767 if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (
is64Bit() ? 8 : 4))
1775 unsigned PrefixLength = strlen(
".init_array");
1776 if (WS.getName().size() > PrefixLength) {
1777 if (WS.getName()[PrefixLength] !=
'.')
1779 ".init_array section priority should start with '.'");
1780 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1783 const auto &DataFrag = cast<MCDataFragment>(Frag);
1785 for (
const uint8_t *
1786 P = (
const uint8_t *)Contents.
data(),
1787 *End = (
const uint8_t *)Contents.
data() + Contents.
size();
1792 for (
const MCFixup &Fixup : DataFrag.getFixups()) {
1796 auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1799 const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1802 if (!TargetSym.isFunction())
1805 std::make_pair(Priority, TargetSym.getIndex()));
1812 uint32_t CodeSectionIndex, DataSectionIndex;
1813 if (
Mode != DwoMode::DwoOnly) {
1814 writeTypeSection(Signatures);
1815 writeImportSection(Imports, DataSize, TableElems.
size());
1816 writeFunctionSection(Functions);
1817 writeTableSection(Tables);
1819 writeEventSection(Events);
1820 writeGlobalSection(Globals);
1821 writeExportSection(Exports);
1822 writeElemSection(TableElems);
1823 writeDataCountSection();
1825 CodeSectionIndex = writeCodeSection(
Asm, Layout, Functions);
1826 DataSectionIndex = writeDataSection(Layout);
1831 for (
auto &Group : Comdats) {
1832 for (
auto &Entry : Group.second) {
1834 Entry.Index += SectionCount;
1838 for (
auto &CustomSection : CustomSections)
1839 writeCustomSection(CustomSection,
Asm, Layout);
1841 if (
Mode != DwoMode::DwoOnly) {
1842 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1844 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1845 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1847 writeCustomRelocSections();
1848 if (ProducersSection)
1849 writeCustomSection(*ProducersSection,
Asm, Layout);
1850 if (TargetFeaturesSection)
1851 writeCustomSection(*TargetFeaturesSection,
Asm, Layout);
1854 return W->OS.tell() - StartOffset;
1857 std::unique_ptr<MCObjectWriter>
1860 return std::make_unique<WasmObjectWriter>(
std::move(MOTW), OS);
1863 std::unique_ptr<MCObjectWriter>
1867 return std::make_unique<WasmObjectWriter>(
std::move(MOTW), OS, DwoOS);
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
reference emplace_back(ArgTypes &&... Args)
static const unsigned InvalidIndex
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
SectionKind getKind() const
void setUsedInReloc() const
LLVM_NODISCARD bool endswith(StringRef Suffix) const
Check if this string ends with the given Suffix.
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This represents an "assembler immediate".
bool relocTypeHasAddend(uint32_t type)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
VariantKind getKind() const
const unsigned WASM_SYMBOL_BINDING_LOCAL
void push_back(const T &Elt)
const uint32_t WasmMetadataVersion
FragmentType getKind() const
void write32le(void *P, uint32_t V)
Defines the object file and target independent interfaces used by the assembler backend to write nati...
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
unsigned getAlignment() const
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
const unsigned WASM_SYMBOL_UNDEFINED
std::string toString(Error E)
Write all error messages (if any) in E to a string.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Encapsulates the layout of an assembly file at a particular point in time.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Base class for the full range of assembler expressions which are needed for parsing.
The access may reference the value stored in memory.
SmallVector< ValType, 1 > Returns
const unsigned WASM_SYMBOL_NO_STRIP
Represent a reference to a symbol from inside an expression.
std::unique_ptr< MCObjectWriter > createWasmDwoObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS)
const uint32_t WasmVersion
Context object for machine code objects.
bool isUsedInInitArray() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
std::string relocTypetoString(uint32_t type)
LLVM_NODISCARD size_t size() const
size - Get the string size.
uint64_t Offset
The offset to apply to the fragment address to form this symbol's value.
Analysis containing CSE Info
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Import information from summary.
The instances of the Type class are immutable: once they are created, they are never changed.
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN
size_t size() const
size - Get the array size.
This represents a section on wasm.
virtual void reset()
lifetime management
unsigned Kind
LLVM RTTI discriminator.
StringRef getName() const
const unsigned WASM_SYMBOL_BINDING_WEAK
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
Get the offset of the given symbol, as computed in the current layout.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
void pwrite(const char *Ptr, size_t Size, uint64_t Offset)
std::unique_ptr< MCObjectWriter > createWasmObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Construct a new Wasm writer instance.
void reportError(SMLoc L, const Twine &Msg)
static void addData(SmallVectorImpl< char > &DataBytes, MCSectionWasm &DataSection)
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
PowerPC TLS Dynamic Call Fixup
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
const unsigned WASM_SYMBOL_EXPLICIT_NAME
void setUndefined()
Mark the symbol as undefined.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
const MCSymbol & getSymbol() const
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MCSymbol * getBeginSymbol()
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
Target - Wrapper for Target specific information.
MCSection * getParent() const
bool hasInstructions() const
Does this fragment have instructions emitted into it? By default this is false, but specific fragment...
iterator insert(iterator I, T &&Elt)
bool isUsedInReloc() const
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::ZeroOrMore, cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate IT block based on arch"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow deprecated IT based on ARMv8"), clEnumValN(NoRestrictedIT, "arm-no-restrict-it", "Allow IT blocks based on ARMv7")))
Adapter to write values to a stream in a particular byte order.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
void write64le(void *P, uint64_t V)
pointer data()
Return a pointer to the vector's buffer, even if empty().
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
StringRef getName() const
Return a constant reference to the value's name.
An abstract base class for streams implementations that also support a pwrite operation.
static MCFixupKind getKindForSize(unsigned Size, bool IsPCRel)
Return the generic fixup kind for a value with the given size.
bool isFunctionTable() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void stable_sort(R &&Range)
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
const uint32_t WasmPageSize
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
StringRef - Represent a constant reference to a string, i.e.
const unsigned WASM_SYMBOL_EXPORTED
static bool isInSymtab(const MCSymbolWasm &Sym)
static bool is64Bit(const char *name)
const MCSymbol * getBaseSymbol(const MCSymbol &Symbol) const
If this symbol is equivalent to A + Constant, return A.
bool empty() const
empty - Check if the array is empty.