17 #include "llvm/Config/llvm-config.h" 38 #define DEBUG_TYPE "mc" 44 static const uint32_t kInitialTableOffset = 1;
49 struct SectionBookkeeping {
53 uint64_t PayloadOffset;
55 uint64_t ContentsOffset;
62 struct WasmSignature {
64 enum { Plain,
Empty, Tombstone } State;
72 WasmSignature() : State(Plain) {}
75 return State == Other.State && Returns == Other.Returns &&
76 Params == Other.Params;
81 struct WasmSignatureDenseMapInfo {
82 static WasmSignature getEmptyKey() {
87 static WasmSignature getTombstoneKey() {
89 Sig.State = WasmSignature::Tombstone;
92 static unsigned getHashValue(
const WasmSignature &Sig) {
93 uintptr_t
Value = Sig.State;
100 static bool isEqual(
const WasmSignature &LHS,
const WasmSignature &RHS) {
109 struct WasmDataSegment {
119 struct WasmFunction {
127 uint64_t InitialValue;
133 struct WasmComdatEntry {
139 struct WasmRelocationEntry {
146 WasmRelocationEntry(uint64_t Offset,
const MCSymbolWasm *Symbol,
147 int64_t Addend,
unsigned Type,
149 :
Offset(Offset),
Symbol(Symbol), Addend(Addend), Type(Type),
150 FixupSection(FixupSection) {}
152 bool hasAddend()
const {
154 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
155 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
156 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
157 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
158 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
167 <<
", Sym=" << *Symbol <<
", Addend=" << Addend
171 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 176 static const uint32_t INVALID_INDEX = -1;
178 struct WasmCustomSection {
187 :
Name(Name),
Section(Section), OutputContentsOffset(0),
188 OutputIndex(INVALID_INDEX) {}
202 std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
205 std::vector<WasmRelocationEntry> CodeRelocations;
209 std::vector<WasmRelocationEntry> DataRelocations;
226 std::vector<WasmCustomSection> CustomSections;
229 CustomSectionsRelocations;
238 unsigned NumFunctionImports = 0;
239 unsigned NumGlobalImports = 0;
240 unsigned NumEventImports = 0;
244 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
246 return TargetObjectWriter->getRelocType(Target, Fixup);
249 void startSection(SectionBookkeeping &
Section,
unsigned SectionId);
250 void startCustomSection(SectionBookkeeping &Section,
StringRef Name);
251 void endSection(SectionBookkeeping &Section);
254 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
258 ~WasmObjectWriter()
override;
261 void reset()
override {
262 CodeRelocations.clear();
263 DataRelocations.clear();
266 TableIndices.
clear();
267 DataLocations.
clear();
268 CustomSectionsRelocations.
clear();
269 SignatureIndices.
clear();
272 DataSegments.
clear();
273 SectionFunctions.
clear();
274 NumFunctionImports = 0;
275 NumGlobalImports = 0;
283 MCValue Target, uint64_t &FixedValue)
override;
295 void writeValueType(
wasm::ValType Ty) { W.
OS <<
static_cast<char>(Ty); }
301 void writeGlobalSection();
306 void writeDataSection();
309 std::vector<WasmRelocationEntry> &Relocations);
310 void writeLinkingMetaDataSection(
312 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
313 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats);
315 void writeCustomRelocSections();
320 uint32_t getProvisionalValue(
const WasmRelocationEntry &RelEntry);
322 uint64_t ContentsOffset);
324 uint32_t getRelocationIndexValue(
const WasmRelocationEntry &RelEntry);
333 WasmObjectWriter::~WasmObjectWriter() {}
336 void WasmObjectWriter::startSection(SectionBookkeeping &
Section,
337 unsigned SectionId) {
339 W.OS <<
char(SectionId);
341 Section.SizeOffset =
W.OS.tell();
348 Section.ContentsOffset =
W.OS.tell();
349 Section.PayloadOffset =
W.OS.tell();
350 Section.Index = SectionCount++;
353 void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
359 Section.PayloadOffset =
W.OS.tell();
365 Section.ContentsOffset =
W.OS.tell();
370 void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
371 uint64_t
Size =
W.OS.tell();
377 Size -= Section.PayloadOffset;
398 void WasmObjectWriter::executePostLayoutBinding(
MCAssembler &Asm,
404 if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
405 const auto &Sec =
static_cast<const MCSectionWasm &
>(S.getSection());
406 auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
409 Sec.getSectionName());
414 void WasmObjectWriter::recordRelocation(
MCAssembler &Asm,
418 uint64_t &FixedValue) {
422 const auto &FixupSection = cast<MCSectionWasm>(*Fragment->
getParent());
428 if (FixupSection.getSectionName().startswith(
".init_array"))
433 "Should not have constructed this");
445 "No relocation available to represent this relative expression");
449 const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
451 if (SymB.isUndefined()) {
453 Twine(
"symbol '") + SymB.getName() +
454 "' can not be undefined in a subtraction expression");
458 assert(!SymB.isAbsolute() &&
"Should have been folded");
459 const MCSection &SecB = SymB.getSection();
460 if (&SecB != &FixupSection) {
462 "Cannot represent a difference across sections");
467 uint64_t K = SymBOffset - FixupOffset;
474 const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->
getSymbol()) :
nullptr;
476 if (SymA && SymA->isVariable()) {
477 const MCExpr *Expr = SymA->getVariableValue();
478 const auto *Inner = cast<MCSymbolRefExpr>(Expr);
495 if (Type == wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32 ||
496 Type == wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32) {
497 if (!FixupSection.getKind().isMetadata())
499 "only supported in metadata sections");
501 const MCSymbol *SectionSymbol =
nullptr;
502 const MCSection &SecA = SymA->getSection();
504 SectionSymbol = SectionFunctions.find(&SecA)->second;
511 SymA = cast<MCSymbolWasm>(SectionSymbol);
516 if (Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) {
517 if (SymA->getName().empty())
519 "supported by wasm");
521 SymA->setUsedInReloc();
524 WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
527 if (FixupSection.isWasmData()) {
528 DataRelocations.push_back(Rec);
529 }
else if (FixupSection.getKind().isText()) {
530 CodeRelocations.push_back(Rec);
531 }
else if (FixupSection.getKind().isMetadata()) {
532 CustomSectionsRelocations[&FixupSection].push_back(Rec);
545 Stream.
pwrite((
char *)Buffer, SizeLen, Offset);
555 Stream.
pwrite((
char *)Buffer, SizeLen, Offset);
562 Stream.
pwrite((
char *)Buffer,
sizeof(Buffer), Offset);
568 auto *Inner = cast<MCSymbolRefExpr>(Expr);
569 return cast<MCSymbolWasm>(&Inner->getSymbol());
579 WasmObjectWriter::getProvisionalValue(
const WasmRelocationEntry &RelEntry) {
580 switch (RelEntry.Type) {
581 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
582 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
586 return TableIndices[Sym];
588 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
590 return getRelocationIndexValue(RelEntry);
591 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
592 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
593 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
595 if (!WasmIndices.count(RelEntry.Symbol))
597 RelEntry.Symbol->getName());
598 return WasmIndices[RelEntry.Symbol];
599 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
600 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32: {
601 const auto &Section =
602 static_cast<const MCSectionWasm &
>(RelEntry.Symbol->getSection());
603 return Section.getSectionOffset() + RelEntry.Addend;
605 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
606 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
607 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
614 const WasmDataSegment &Segment = DataSegments[Ref.
Segment];
616 return Segment.Offset + Ref.
Offset + RelEntry.Addend;
630 if (Frag.hasInstructions())
633 if (
auto *
Align = dyn_cast<MCAlignFragment>(&Frag)) {
634 if (
Align->getValueSize() != 1)
640 DataBytes.
size() +
Align->getMaxBytesToEmit());
641 DataBytes.
resize(Size, Value);
642 }
else if (
auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
644 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
646 DataBytes.
insert(DataBytes.
end(), Fill->getValueSize() * NumValues,
648 }
else if (
auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
652 const auto &DataFrag = cast<MCDataFragment>(Frag);
654 DataBytes.
insert(DataBytes.
end(), Contents.begin(), Contents.end());
662 WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
663 if (RelEntry.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) {
664 if (!TypeIndices.count(RelEntry.Symbol))
666 RelEntry.Symbol->getName());
667 return TypeIndices[RelEntry.Symbol];
670 return RelEntry.Symbol->getIndex();
675 void WasmObjectWriter::applyRelocations(
678 for (
const WasmRelocationEntry &RelEntry : Relocations) {
679 uint64_t
Offset = ContentsOffset +
680 RelEntry.FixupSection->getSectionOffset() +
686 switch (RelEntry.Type) {
687 case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
688 case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
689 case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
690 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
691 case wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB:
694 case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
695 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
696 case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
697 case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
700 case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
701 case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
711 if (Signatures.
empty())
719 for (
const WasmSignature &Sig : Signatures) {
745 writeString(
Import.Module);
746 writeString(
Import.Field);
779 if (Functions.
empty())
786 for (
const WasmFunction &Func : Functions)
792 void WasmObjectWriter::writeGlobalSection() {
800 for (
const WasmGlobal &Global : Globals) {
801 writeValueType(static_cast<wasm::ValType>(Global.Type.Type));
802 W.OS <<
char(Global.Type.Mutable);
846 if (TableElems.
empty())
867 void WasmObjectWriter::writeCodeSection(
const MCAssembler &Asm,
870 if (Functions.
empty())
875 CodeSectionIndex = Section.Index;
879 for (
const WasmFunction &Func : Functions) {
880 auto &FuncSection =
static_cast<MCSectionWasm &
>(Func.Sym->getSection());
883 if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
887 FuncSection.setSectionOffset(
W.OS.tell() - Section.ContentsOffset);
892 applyRelocations(CodeRelocations, Section.ContentsOffset);
897 void WasmObjectWriter::writeDataSection() {
898 if (DataSegments.empty())
903 DataSectionIndex = Section.Index;
907 for (
const WasmDataSegment &Segment : DataSegments) {
913 Segment.Section->setSectionOffset(
W.OS.tell() - Section.ContentsOffset);
914 W.OS << Segment.Data;
918 applyRelocations(DataRelocations, Section.ContentsOffset);
923 void WasmObjectWriter::writeRelocSection(
925 std::vector<WasmRelocationEntry> &Relocs) {
938 Relocs.begin(), Relocs.end(),
939 [](
const WasmRelocationEntry &A,
const WasmRelocationEntry &
B) {
940 return (A.Offset + A.FixupSection->getSectionOffset()) <
941 (
B.Offset +
B.FixupSection->getSectionOffset());
945 startCustomSection(Section, std::string(
"reloc.") + Name.
str());
949 for (
const WasmRelocationEntry &RelEntry : Relocs) {
951 RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
954 W.OS <<
char(RelEntry.Type);
957 if (RelEntry.hasAddend())
964 void WasmObjectWriter::writeCustomRelocSections() {
965 for (
const auto &Sec : CustomSections) {
966 auto &Relocations = CustomSectionsRelocations[Sec.Section];
967 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
971 void WasmObjectWriter::writeLinkingMetaDataSection(
973 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
974 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats) {
976 startCustomSection(Section,
"linking");
979 SectionBookkeeping SubSection;
980 if (SymbolInfos.
size() != 0) {
993 writeString(Sym.Name);
996 writeString(Sym.Name);
1005 CustomSections[Sym.ElementIndex].OutputIndex;
1013 endSection(SubSection);
1016 if (DataSegments.size()) {
1019 for (
const WasmDataSegment &Segment : DataSegments) {
1020 writeString(Segment.Name);
1024 endSection(SubSection);
1027 if (!InitFuncs.empty()) {
1030 for (
auto &StartFunc : InitFuncs) {
1034 endSection(SubSection);
1037 if (Comdats.size()) {
1040 for (
const auto &
C : Comdats) {
1041 writeString(
C.first);
1044 for (
const WasmComdatEntry &Entry :
C.second) {
1049 endSection(SubSection);
1052 endSection(Section);
1055 void WasmObjectWriter::writeCustomSections(
const MCAssembler &Asm,
1057 for (
auto &CustomSection : CustomSections) {
1059 auto *Sec = CustomSection.Section;
1060 startCustomSection(Section, CustomSection.Name);
1062 Sec->setSectionOffset(
W.OS.tell() - Section.ContentsOffset);
1065 CustomSection.OutputContentsOffset = Section.ContentsOffset;
1066 CustomSection.OutputIndex = Section.Index;
1068 endSection(Section);
1071 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1072 applyRelocations(Relocations, CustomSection.OutputContentsOffset);
1078 assert(TypeIndices.count(&Symbol));
1079 return TypeIndices[&
Symbol];
1084 assert(TypeIndices.count(&Symbol));
1085 return TypeIndices[&
Symbol];
1088 void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1094 S.Returns = Sig->Returns;
1095 S.Params = Sig->Params;
1098 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.
size()));
1100 Signatures.push_back(S);
1101 TypeIndices[&
Symbol] = Pair.first->second;
1104 <<
" new:" << Pair.second <<
"\n");
1105 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1108 void WasmObjectWriter::registerEventType(
const MCSymbolWasm &Symbol) {
1115 S.Returns = Sig->Returns;
1116 S.Params = Sig->Params;
1119 auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.
size()));
1121 Signatures.push_back(S);
1122 TypeIndices[&
Symbol] = Pair.first->second;
1124 LLVM_DEBUG(
dbgs() <<
"registerEventType: " << Symbol <<
" new:" << Pair.second
1126 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1148 uint64_t WasmObjectWriter::writeObject(
MCAssembler &Asm,
1150 uint64_t StartOffset =
W.OS.tell();
1163 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1197 if (WS.isFunction())
1198 registerFunctionType(WS);
1201 registerEventType(WS);
1203 if (WS.isTemporary())
1207 if (!WS.isDefined() && !WS.isComdat()) {
1208 if (WS.isFunction()) {
1210 Import.
Module = WS.getImportModule();
1211 Import.
Field = WS.getImportName();
1213 Import.
SigIndex = getFunctionType(WS);
1215 WasmIndices[&WS] = NumFunctionImports++;
1216 }
else if (WS.isGlobal()) {
1221 Import.
Module = WS.getImportModule();
1222 Import.
Field = WS.getImportName();
1224 Import.
Global = WS.getGlobalType();
1226 WasmIndices[&WS] = NumGlobalImports++;
1227 }
else if (WS.isEvent()) {
1232 Import.
Module = WS.getImportModule();
1233 Import.
Field = WS.getImportName();
1238 WasmIndices[&WS] = NumEventImports++;
1254 if (Section.getKind().isText())
1257 if (Section.isWasmData()) {
1258 uint32_t SegmentIndex = DataSegments.size();
1259 DataSize =
alignTo(DataSize, Section.getAlignment());
1260 DataSegments.emplace_back();
1261 WasmDataSegment &Segment = DataSegments.back();
1263 Segment.Offset = DataSize;
1265 addData(Segment.Data, Section);
1266 Segment.Alignment =
Log2_32(Section.getAlignment());
1268 DataSize += Segment.Data.size();
1269 Section.setSegmentIndex(SegmentIndex);
1272 Comdats[
C->
getName()].emplace_back(
1277 assert(Sec.getKind().isMetadata());
1282 if (Name.startswith(
".custom_section."))
1283 Name = Name.substr(strlen(
".custom_section."));
1285 MCSymbol *Begin = Sec.getBeginSymbol();
1287 WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1288 if (SectionName != Begin->
getName())
1290 Twine(SectionName));
1292 CustomSections.emplace_back(Name, &Section);
1297 for (
const MCSymbol &S : Asm.symbols()) {
1300 if (S.isTemporary() && S.getName().empty())
1305 dbgs() <<
"MCSymbol: " <<
toString(WS.getType()) <<
" '" << S <<
"'" 1306 <<
" isDefined=" << S.isDefined() <<
" isExternal=" 1307 << S.isExternal() <<
" isTemporary=" << S.isTemporary()
1308 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1309 <<
" isVariable=" << WS.isVariable() <<
"\n");
1311 if (WS.isVariable())
1313 if (WS.isComdat() && !WS.isDefined())
1316 if (WS.isFunction()) {
1318 if (WS.isDefined()) {
1319 if (WS.getOffset() != 0)
1321 "function sections must contain one function each");
1323 if (WS.getSize() == 0)
1325 "function symbols must have a size set with .size");
1328 Index = NumFunctionImports + Functions.
size();
1330 Func.SigIndex = getFunctionType(WS);
1332 WasmIndices[&WS] =
Index;
1335 auto &Section =
static_cast<MCSectionWasm &
>(WS.getSection());
1337 Comdats[
C->
getName()].emplace_back(
1342 Index = WasmIndices.find(&WS)->second;
1347 }
else if (WS.isData()) {
1348 if (WS.isTemporary() && !WS.getSize())
1351 if (!WS.isDefined()) {
1362 if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
1365 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1366 assert(DataSection.isWasmData());
1371 DataSection.getSegmentIndex(),
1373 static_cast<uint32_t>(Size)};
1374 DataLocations[&WS] =
Ref;
1375 LLVM_DEBUG(
dbgs() <<
" -> segment index: " << Ref.Segment <<
"\n");
1377 }
else if (WS.isGlobal()) {
1384 << WasmIndices.find(&WS)->second <<
"\n");
1386 }
else if (WS.isEvent()) {
1389 if (WS.isDefined()) {
1390 Index = NumEventImports + Events.
size();
1394 WasmIndices[&WS] =
Index;
1398 Index = WasmIndices.find(&WS)->second;
1400 LLVM_DEBUG(
dbgs() <<
" -> event index: " << WasmIndices.find(&WS)->second
1412 for (
const MCSymbol &S : Asm.symbols()) {
1413 if (!S.isVariable())
1421 LLVM_DEBUG(
dbgs() << WS.getName() <<
": weak alias of '" << *ResolvedSym
1424 if (WS.isFunction()) {
1425 assert(WasmIndices.count(ResolvedSym) > 0);
1426 uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second;
1427 WasmIndices[&WS] = WasmIndex;
1429 }
else if (WS.isData()) {
1430 assert(DataLocations.count(ResolvedSym) > 0);
1432 DataLocations.find(ResolvedSym)->second;
1433 DataLocations[&WS] =
Ref;
1441 for (
const MCSymbol &S : Asm.symbols()) {
1454 if (!WS.isExternal() && WS.isDefined())
1456 if (WS.isUndefined())
1458 if (WS.getName() != WS.getImportName())
1462 Info.
Name = WS.getName();
1463 Info.
Kind = WS.getType();
1466 assert(WasmIndices.count(&WS) > 0);
1468 }
else if (WS.isDefined()) {
1469 assert(DataLocations.count(&WS) > 0);
1470 Info.
DataRef = DataLocations.find(&WS)->second;
1472 WS.setIndex(SymbolInfos.
size());
1477 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1481 if (Rel.Type != wasm::R_WEBASSEMBLY_TABLE_INDEX_I32 &&
1482 Rel.Type != wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB)
1484 assert(Rel.Symbol->isFunction());
1486 uint32_t FunctionIndex = WasmIndices.find(&WS)->second;
1487 uint32_t TableIndex = TableElems.
size() + kInitialTableOffset;
1488 if (TableIndices.try_emplace(&WS, TableIndex).second) {
1490 <<
" to table: " << TableIndex <<
"\n");
1492 registerFunctionType(WS);
1496 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1497 HandleReloc(RelEntry);
1498 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1499 HandleReloc(RelEntry);
1505 if (WS.getSectionName().startswith(
".fini_array"))
1507 if (!WS.getSectionName().startswith(
".init_array"))
1509 if (WS.getFragmentList().empty())
1513 if (WS.getFragmentList().size() != 3)
1516 auto IT = WS.begin();
1525 if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (
is64Bit() ? 8 : 4))
1532 uint16_t Priority = UINT16_MAX;
1533 unsigned PrefixLength = strlen(
".init_array");
1534 if (WS.getSectionName().size() > PrefixLength) {
1535 if (WS.getSectionName()[PrefixLength] !=
'.')
1537 ".init_array section priority should start with '.'");
1538 if (WS.getSectionName()
1539 .substr(PrefixLength + 1)
1540 .getAsInteger(10, Priority))
1543 const auto &DataFrag = cast<MCDataFragment>(Frag);
1545 for (
const uint8_t *
1546 p = (
const uint8_t *)Contents.data(),
1547 *
end = (
const uint8_t *)Contents.data() + Contents.size();
1552 for (
const MCFixup &Fixup : DataFrag.getFixups()) {
1561 if (Sym->getSymbol().getIndex() == INVALID_INDEX)
1564 std::make_pair(Priority, Sym->getSymbol().getIndex()));
1571 writeTypeSection(Signatures);
1572 writeImportSection(Imports, DataSize, TableElems.
size());
1573 writeFunctionSection(Functions);
1576 writeGlobalSection();
1577 writeEventSection(Events);
1578 writeExportSection(Exports);
1579 writeElemSection(TableElems);
1580 writeCodeSection(Asm, Layout, Functions);
1582 writeCustomSections(Asm, Layout);
1583 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1584 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1585 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1586 writeCustomRelocSections();
1589 return W.OS.tell() - StartOffset;
1592 std::unique_ptr<MCObjectWriter>
1595 return llvm::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
Instances of this class represent a uniqued identifier for a section in the current translation unit...
static const MCSymbolWasm * ResolveSymbol(const MCSymbolWasm &Symbol)
const_iterator end(StringRef path)
Get end iterator over path.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
SectionKind getKind() const
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
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.
bool isVariable() const
isVariable - Check if this is a variable symbol.
This represents an "assembler immediate".
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset)
const unsigned WASM_SYMBOL_BINDING_LOCAL
void push_back(const T &Elt)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
const uint32_t WasmMetadataVersion
StringRef getSectionName() const
static MCFixupKind getKindForSize(unsigned Size, bool isPCRel)
Return the generic fixup kind for a value with the given size.
FragmentType getKind() const
void write32le(void *P, uint32_t V)
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
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
Export information to summary.
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
MCContext & getContext() const
static void WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset)
const unsigned WASM_SYMBOL_UNDEFINED
int64_t getConstant() const
const MCSymbolRefExpr * getSymB() const
amdgpu Simplify well known AMD library false Value Value const Twine & Name
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.
Base class for the full range of assembler expressions which are needed for parsing.
The access may reference the value stored in memory.
Represent a reference to a symbol from inside an expression.
static unsigned getRelocType(const MCValue &Target, const MCFixupKind FixupKind, const bool IsPCRel)
Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
const uint32_t WasmVersion
Context object for machine code objects.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
static bool isEqual(const Function &Caller, const Function &Callee)
const wasm::WasmSignature * getSignature() const
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
std::string relocTypetoString(uint32_t type)
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.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
static bool is64Bit(const char *name)
virtual void reset()
lifetime management
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.
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.
const MCSymbolRefExpr * getSymA() const
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)
uint32_t getOffset() const
void writeSectionData(raw_ostream &OS, const MCSection *Section, const MCAsmLayout &Layout) const
Emit the section contents to OS.
const MCExpr * getSize() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
PowerPC TLS Dynamic Call Fixup
const StringRef getImportModule() const
const unsigned WASM_SYMBOL_EXPLICIT_NAME
MCAsmBackend & getBackend() const
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.
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.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
void emplace_back(ArgTypes &&... Args)
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.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
StringRef getName() const
getName - Get the symbol name.
An abstract base class for streams implementations that also support a pwrite operation.
static void WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
WasmDataReference DataRef
LLVM Value Representation.
Generic interface to target specific assembler backends.
This class implements an extremely fast bulk output stream that can only output to a stream...
const MCExpr * getValue() const
const uint32_t WasmPageSize
StringRef - Represent a constant reference to a string, i.e.
const StringRef getImportName() const
bool operator==(uint64_t V1, const APInt &V2)
static bool isInSymtab(const MCSymbolWasm &Sym)
void setIndex(uint32_t Value) const
Set the (implementation defined) index.
MCFixupKind getKind() const
bool empty() const
empty - Check if the array is empty.