17#include "llvm/Config/config.h"
66 unsigned MinInsnLength = Context.getAsmInfo().getMinInstAlignment();
67 if (MinInsnLength == 1)
69 if (AddrDelta % MinInsnLength != 0) {
73 return AddrDelta / MinInsnLength;
77 UseRelocs = Ctx.getAsmInfo().doesDwarfUseRelocationsAcrossSections();
80 Ctx.getObjectFileInfo()->getDwarfLineStrSection();
81 assert(DwarfLineStrSection &&
"DwarfLineStrSection must not be NULL");
134static inline const MCExpr *
152 auto I = MCLineDivisions.find(Sec);
153 if (
I == MCLineDivisions.end())
156 auto &Entries =
I->second;
170 Entries.push_back(EndEntry);
181 unsigned FileNum, LastLine, Column, Flags, Isa, Discriminator;
197 bool EndEntryEmitted =
false;
198 for (
auto It = LineEntries.begin(); It != LineEntries.end(); ++It) {
199 auto LineEntry = *It;
200 MCSymbol *CurrLabel = LineEntry.getLabel();
203 if (LineEntry.LineStreamLabel) {
205 auto *Label = CurrLabel;
206 auto NextIt = It + 1;
211 if (!Label && NextIt != LineEntries.end()) {
212 Label = NextIt->getLabel();
218 MCOS->
emitLabel(LineEntry.LineStreamLabel, LineEntry.StreamLabelDefLoc);
222 if (LineEntry.IsEndEntry) {
226 EndEntryEmitted =
true;
230 int64_t LineDelta =
static_cast<int64_t
>(LineEntry.getLine()) - LastLine;
232 if (FileNum != LineEntry.getFileNum()) {
233 FileNum = LineEntry.getFileNum();
234 MCOS->
emitInt8(dwarf::DW_LNS_set_file);
237 if (Column != LineEntry.getColumn()) {
238 Column = LineEntry.getColumn();
239 MCOS->
emitInt8(dwarf::DW_LNS_set_column);
242 if (Discriminator != LineEntry.getDiscriminator() &&
244 Discriminator = LineEntry.getDiscriminator();
246 MCOS->
emitInt8(dwarf::DW_LNS_extended_op);
248 MCOS->
emitInt8(dwarf::DW_LNE_set_discriminator);
251 if (Isa != LineEntry.getIsa()) {
252 Isa = LineEntry.getIsa();
253 MCOS->
emitInt8(dwarf::DW_LNS_set_isa);
257 Flags = LineEntry.getFlags();
258 MCOS->
emitInt8(dwarf::DW_LNS_negate_stmt);
261 MCOS->
emitInt8(dwarf::DW_LNS_set_basic_block);
263 MCOS->
emitInt8(dwarf::DW_LNS_set_prologue_end);
265 MCOS->
emitInt8(dwarf::DW_LNS_set_epilogue_begin);
274 LastLine = LineEntry.getLine();
275 PrevLabel = CurrLabel;
276 IsAtStartSeq =
false;
284 if (!EndEntryEmitted && !IsAtStartSeq)
293 auto *LineSym = ctx.createTempSymbol();
295 const MCDwarfLoc &DwarfLoc = ctx.getCurrentDwarfLoc();
314 if (LineTables.empty())
318 std::optional<MCDwarfLineStr> LineStr;
320 LineStr.emplace(context);
326 for (
const auto &CUIDTablePair : LineTables) {
327 CUIDTablePair.second.emitCU(MCOS, Params, LineStr);
331 LineStr->emitSection(MCOS);
336 if (!HasSplitLineTable)
338 std::optional<MCDwarfLineStr> NoLineStr(std::nullopt);
340 MCOS.
emitLabel(Header.Emit(&MCOS, Params, {}, NoLineStr).second);
343std::pair<MCSymbol *, MCSymbol *>
345 std::optional<MCDwarfLineStr> &LineStr)
const {
346 static const char StandardOpcodeLengths[] = {
360 assert(std::size(StandardOpcodeLengths) >=
362 return Emit(MCOS, Params,
370 if (!Context.getAsmInfo().doesSetDirectiveSuppressReloc())
374 MCSymbol *ABS = Context.createTempSymbol();
394 if (!LineStrings.isFinalized())
395 LineStrings.finalizeInOrder();
397 Data.resize(LineStrings.getSize());
403 return LineStrings.add(Path);
412 if (Ctx.getAsmInfo().needsDwarfSectionOffsetDirective()) {
422void MCDwarfLineTableHeader::emitV2FileDirTables(
MCStreamer *MCOS)
const {
443 bool EmitMD5,
bool HasAnySource,
444 std::optional<MCDwarfLineStr> &LineStr) {
456 StringRef(
reinterpret_cast<const char *
>(Cksum.data()), Cksum.size()));
467 LineStr->emitRef(MCOS, Source);
475void MCDwarfLineTableHeader::emitV5FileDirTables(
476 MCStreamer *MCOS, std::optional<MCDwarfLineStr> &LineStr)
const {
483 : dwarf::DW_FORM_string);
486 SmallString<256> Dir;
493 CompDir = LineStr->getSaver().save(CompDir);
497 LineStr->emitRef(MCOS, CompDir);
499 LineStr->emitRef(MCOS, Dir);
513 uint64_t Entries = 2;
521 : dwarf::DW_FORM_string);
531 : dwarf::DW_FORM_string);
541 "No root file and no .file directives");
548std::pair<MCSymbol *, MCSymbol *>
551 std::optional<MCDwarfLineStr> &LineStr)
const {
571 if (LineTableVersion >= 5) {
591 if (LineTableVersion >= 4)
599 for (
char Length : StandardOpcodeLengths)
604 if (LineTableVersion >= 5)
605 emitV5FileDirTables(MCOS, LineStr);
607 emitV2FileDirTables(MCOS);
613 return std::make_pair(LineStartSym, LineEndSym);
617 std::optional<MCDwarfLineStr> &LineStr)
const {
618 MCSymbol *LineEndSym = Header.Emit(MCOS, Params, LineStr).second;
621 for (
const auto &LineSec : MCLineSections.getMCLineEntries())
622 emitOne(MCOS, LineSec.first, LineSec.second);
631 std::optional<MD5::MD5Result> Checksum,
632 std::optional<StringRef> Source,
633 uint16_t DwarfVersion,
unsigned FileNumber) {
634 return Header.tryGetFile(Directory, FileName, Checksum, Source, DwarfVersion,
640 std::optional<MD5::MD5Result> Checksum) {
643 return RootFile.
Checksum == Checksum;
648 std::optional<MD5::MD5Result> Checksum,
649 std::optional<StringRef> Source,
650 uint16_t DwarfVersion,
unsigned FileNumber) {
653 if (FileName.
empty()) {
654 FileName =
"<stdin>";
666 if (FileNumber == 0) {
674 if (!IterBool.second)
675 return IterBool.first->second;
685 if (!File.Name.empty())
689 if (Directory.
empty()) {
692 if (!tFileName.
empty()) {
694 if (!Directory.
empty())
695 FileName = tFileName;
702 if (Directory.
empty()) {
716 File.Name = std::string(FileName);
717 File.DirIndex = DirIndex;
718 File.Checksum = Checksum;
720 File.Source = Source;
721 if (Source.has_value())
730 int64_t LineDelta,
uint64_t AddrDelta) {
745 int64_t LineDelta,
uint64_t AddrDelta,
748 bool NeedCopy =
false;
760 if (AddrDelta == MaxSpecialAddrDelta)
761 Out.
push_back(dwarf::DW_LNS_const_add_pc);
762 else if (AddrDelta) {
766 Out.
push_back(dwarf::DW_LNS_extended_op);
768 Out.
push_back(dwarf::DW_LNE_end_sequence);
779 Out.
push_back(dwarf::DW_LNS_advance_line);
788 if (LineDelta == 0 && AddrDelta == 0) {
797 if (AddrDelta < 256 + MaxSpecialAddrDelta) {
806 Opcode = Temp + (AddrDelta - MaxSpecialAddrDelta) * Params.
DWARF2LineRange;
808 Out.
push_back(dwarf::DW_LNS_const_add_pc);
821 assert(Temp <= 255 &&
"Buggy special opcode encoding.");
844 ? dwarf::DW_FORM_sec_offset
846 : dwarf::DW_FORM_data4);
847 EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, SecOffsetForm);
850 EmitAbbrev(MCOS, dwarf::DW_AT_ranges, SecOffsetForm);
852 EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
853 EmitAbbrev(MCOS, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr);
855 EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
857 EmitAbbrev(MCOS, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string);
859 if (!DwarfDebugFlags.
empty())
860 EmitAbbrev(MCOS, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string);
861 EmitAbbrev(MCOS, dwarf::DW_AT_producer, dwarf::DW_FORM_string);
864 EmitAbbrev(MCOS, dwarf::DW_AT_language_name, dwarf::DW_FORM_data2);
866 EmitAbbrev(MCOS, dwarf::DW_AT_language, dwarf::DW_FORM_data2);
874 EmitAbbrev(MCOS, dwarf::DW_AT_name, dwarf::DW_FORM_string);
875 EmitAbbrev(MCOS, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data4);
876 EmitAbbrev(MCOS, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data4);
877 EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr);
889 const MCSymbol *InfoSectionSymbol) {
896 unsigned UnitLengthBytes =
902 int Length = UnitLengthBytes + 2 + OffsetSize + 1 + 1;
908 int Pad = 2 * AddrSize - (
Length & (2 * AddrSize - 1));
909 if (Pad == 2 * AddrSize)
915 Length += 2 * AddrSize * Sections.size();
930 if (InfoSectionSymbol)
940 for(
int i = 0; i < Pad; i++)
946 const MCSymbol *StartSymbol = Sec->getBeginSymbol();
947 MCSymbol *EndSymbol = Sec->getEndSymbol(context);
948 assert(StartSymbol &&
"StartSymbol must not be NULL");
949 assert(EndSymbol &&
"EndSymbol must not be NULL");
967 const MCSymbol *AbbrevSectionSymbol,
982 unsigned UnitLengthBytes =
1004 MCOS->
emitInt8(dwarf::DW_UT_compile);
1009 if (AbbrevSectionSymbol)
1025 if (LineSectionSymbol)
1043 const auto TextSection = Sections.begin();
1044 assert(TextSection != Sections.end() &&
"No text section found");
1046 MCSymbol *StartSymbol = (*TextSection)->getBeginSymbol();
1047 MCSymbol *EndSymbol = (*TextSection)->getEndSymbol(context);
1048 assert(StartSymbol &&
"StartSymbol must not be NULL");
1049 assert(EndSymbol &&
"EndSymbol must not be NULL");
1063 if (MCDwarfDirs.
size() > 0) {
1072 MCDwarfFiles.
empty()
1086 if (!DwarfDebugFlags.
empty()){
1093 if (!DwarfDebugProducer.
empty())
1101 MCOS->
emitInt16(dwarf::DW_LNAME_Assembly);
1106 MCOS->
emitInt16(dwarf::DW_LANG_Mips_Assembler);
1112 const std::vector<MCGenDwarfLabelEntry> &Entries =
1114 for (
const auto &Entry : Entries) {
1159 const MCSymbol *StartSymbol = Sec->getBeginSymbol();
1160 const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
1161 const MCExpr *SectionStartAddr =
1163 const MCExpr *SectionSize =
1165 MCOS->
emitInt8(dwarf::DW_RLE_start_length);
1166 MCOS->
emitValue(SectionStartAddr, AddrSize);
1169 MCOS->
emitInt8(dwarf::DW_RLE_end_of_list);
1176 const MCSymbol *StartSymbol = Sec->getBeginSymbol();
1177 const MCSymbol *EndSymbol = Sec->getEndSymbol(context);
1180 const MCExpr *SectionStartAddr =
1183 MCOS->
emitValue(SectionStartAddr, AddrSize);
1186 const MCExpr *SectionSize =
1197 return RangesSymbol;
1209 bool CreateDwarfSectionSymbols =
1211 MCSymbol *LineSectionSymbol =
nullptr;
1212 if (CreateDwarfSectionSymbols)
1214 MCSymbol *AbbrevSectionSymbol =
nullptr;
1215 MCSymbol *InfoSectionSymbol =
nullptr;
1228 const bool UseRangesSection =
1231 CreateDwarfSectionSymbols |= UseRangesSection;
1234 if (CreateDwarfSectionSymbols) {
1239 if (CreateDwarfSectionSymbols) {
1249 if (UseRangesSection) {
1258 EmitGenDwarfInfo(MCOS, AbbrevSectionSymbol, LineSectionSymbol, RangesSymbol);
1270 if (Symbol->isTemporary())
1281 if (Name.starts_with(
"_"))
1282 Name = Name.
substr(1, Name.size()-1);
1289 unsigned CurBuffer =
SrcMgr.FindBufferContainingLoc(
Loc);
1290 unsigned LineNumber =
SrcMgr.FindLineNumber(
Loc, CurBuffer);
1305 auto ReplaceReg = [=](
unsigned &Reg) {
1311 ReplaceReg(
F.Register);
1312 ReplaceReg(
F.Register2);
1316 ReplaceReg(
F.Register);
1321 ReplaceReg(
F.Register);
1326 ReplaceReg(
F.Register);
1327 ReplaceReg(
F.MaskRegister);
1330 ReplaceReg(
F.Register);
1331 ReplaceReg(
F.SpillRegister);
1332 ReplaceReg(
F.MaskRegister);
1337 std::visit(Visitor, ExtraFields);
1351 unsigned symbolEncoding) {
1353 unsigned format = symbolEncoding & 0x0f;
1372 unsigned symbolEncoding,
bool isEH) {
1385 unsigned symbolEncoding) {
1396class FrameEmitterImpl {
1397 int64_t CFAOffset = 0;
1398 int64_t InitialCFAOffset = 0;
1400 MCObjectStreamer &Streamer;
1403 FrameEmitterImpl(
bool IsEH, MCObjectStreamer &Streamer)
1404 : IsEH(IsEH), Streamer(Streamer) {}
1407 void EmitCompactUnwind(
const MCDwarfFrameInfo &frame);
1409 const MCSymbol &EmitCIE(
const MCDwarfFrameInfo &
F);
1410 void EmitFDE(
const MCSymbol &cieStart,
const MCDwarfFrameInfo &frame,
1411 bool LastInSection,
const MCSymbol &SectionStart);
1413 MCSymbol *BaseLabel);
1414 void emitCFIInstruction(
const MCCFIInstruction &Instr);
1425 if (DwarfReg < 32) {
1426 OS <<
uint8_t(dwarf::DW_OP_reg0 + DwarfReg);
1428 OS <<
uint8_t(dwarf::DW_OP_regx);
1435 auto *MRI = Streamer.getContext().getRegisterInfo();
1437 switch (
Instr.getOperation()) {
1439 unsigned Reg1 =
Instr.getRegister();
1440 unsigned Reg2 =
Instr.getRegister2();
1442 Reg1 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg1);
1443 Reg2 = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg2);
1445 Streamer.emitInt8(dwarf::DW_CFA_register);
1446 Streamer.emitULEB128IntValue(Reg1);
1447 Streamer.emitULEB128IntValue(Reg2);
1451 Streamer.emitInt8(dwarf::DW_CFA_GNU_window_save);
1455 Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state);
1459 Streamer.emitInt8(dwarf::DW_CFA_AARCH64_negate_ra_state_with_pc);
1463 Streamer.emitInt8(dwarf::DW_CFA_AARCH64_set_ra_state);
1464 Streamer.emitULEB128IntValue(
Instr.getRASignState());
1474 Streamer.emitSLEB128Value(Factored);
1476 Streamer.emitSLEB128IntValue(
Instr.getRASignOffset());
1481 unsigned Reg =
Instr.getRegister();
1482 Streamer.emitInt8(dwarf::DW_CFA_undefined);
1483 Streamer.emitULEB128IntValue(
Reg);
1488 const bool IsRelative =
1491 Streamer.emitInt8(dwarf::DW_CFA_def_cfa_offset);
1494 CFAOffset +=
Instr.getOffset();
1496 CFAOffset =
Instr.getOffset();
1498 Streamer.emitULEB128IntValue(CFAOffset);
1503 unsigned Reg =
Instr.getRegister();
1505 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(
Reg);
1506 Streamer.emitInt8(dwarf::DW_CFA_def_cfa);
1507 Streamer.emitULEB128IntValue(
Reg);
1508 CFAOffset =
Instr.getOffset();
1509 Streamer.emitULEB128IntValue(CFAOffset);
1514 unsigned Reg =
Instr.getRegister();
1516 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(
Reg);
1517 Streamer.emitInt8(dwarf::DW_CFA_def_cfa_register);
1518 Streamer.emitULEB128IntValue(
Reg);
1524 unsigned Reg =
Instr.getRegister();
1526 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(
Reg);
1527 Streamer.emitIntValue(dwarf::DW_CFA_LLVM_def_aspace_cfa, 1);
1528 Streamer.emitULEB128IntValue(
Reg);
1529 CFAOffset =
Instr.getOffset();
1530 Streamer.emitULEB128IntValue(CFAOffset);
1531 Streamer.emitULEB128IntValue(
Instr.getAddressSpace());
1537 const bool IsRelative =
1540 unsigned Reg =
Instr.getRegister();
1542 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(
Reg);
1550 Streamer.emitInt8(dwarf::DW_CFA_offset_extended_sf);
1551 Streamer.emitULEB128IntValue(
Reg);
1552 Streamer.emitSLEB128IntValue(
Offset);
1553 }
else if (
Reg < 64) {
1554 Streamer.emitInt8(dwarf::DW_CFA_offset +
Reg);
1555 Streamer.emitULEB128IntValue(
Offset);
1557 Streamer.emitInt8(dwarf::DW_CFA_offset_extended);
1558 Streamer.emitULEB128IntValue(
Reg);
1559 Streamer.emitULEB128IntValue(
Offset);
1564 Streamer.emitInt8(dwarf::DW_CFA_remember_state);
1567 Streamer.emitInt8(dwarf::DW_CFA_restore_state);
1570 unsigned Reg =
Instr.getRegister();
1571 Streamer.emitInt8(dwarf::DW_CFA_same_value);
1572 Streamer.emitULEB128IntValue(
Reg);
1576 unsigned Reg =
Instr.getRegister();
1578 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(
Reg);
1580 Streamer.emitInt8(dwarf::DW_CFA_restore |
Reg);
1582 Streamer.emitInt8(dwarf::DW_CFA_restore_extended);
1583 Streamer.emitULEB128IntValue(
Reg);
1588 Streamer.emitInt8(dwarf::DW_CFA_GNU_args_size);
1589 Streamer.emitULEB128IntValue(
Instr.getOffset());
1593 Streamer.emitBytes(
Instr.getValues());
1597 Streamer.emitLabel(
Instr.getCfiLabel(),
Instr.getLoc());
1600 unsigned Reg =
Instr.getRegister();
1602 Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(
Reg);
1608 Streamer.emitInt8(dwarf::DW_CFA_val_offset_sf);
1609 Streamer.emitULEB128IntValue(
Reg);
1610 Streamer.emitSLEB128IntValue(
Offset);
1612 Streamer.emitInt8(dwarf::DW_CFA_val_offset);
1613 Streamer.emitULEB128IntValue(
Reg);
1614 Streamer.emitULEB128IntValue(
Offset);
1634 const auto &Fields =
1640 if (Fields.Reg1SizeInBits % 8 == 0) {
1641 OSBlock << uint8_t(dwarf::DW_OP_piece);
1644 OSBlock << uint8_t(dwarf::DW_OP_bit_piece);
1649 if (Fields.Reg2SizeInBits % 8 == 0) {
1650 OSBlock << uint8_t(dwarf::DW_OP_piece);
1653 OSBlock << uint8_t(dwarf::DW_OP_bit_piece);
1658 Streamer.emitInt8(dwarf::DW_CFA_expression);
1659 Streamer.emitULEB128IntValue(Fields.Register);
1660 Streamer.emitULEB128IntValue(
Block.size());
1689 const auto &Fields =
1696 if (VRs.size() == 1 && VRs[0].SizeInBits % 8 == 0) {
1698 OSBlock << uint8_t(dwarf::DW_OP_LLVM_user)
1699 << uint8_t(dwarf::DW_OP_LLVM_offset_uconst);
1700 encodeULEB128((VRs[0].SizeInBits / 8) * VRs[0].Lane, OSBlock);
1702 for (
const auto &VR : VRs) {
1707 OSBlock << uint8_t(dwarf::DW_OP_bit_piece);
1713 Streamer.emitInt8(dwarf::DW_CFA_expression);
1714 Streamer.emitULEB128IntValue(Fields.Register);
1715 Streamer.emitULEB128IntValue(
Block.size());
1731 const auto &Fields =
1737 OSBlock << uint8_t(dwarf::DW_OP_swap);
1738 OSBlock << uint8_t(dwarf::DW_OP_LLVM_user)
1739 << uint8_t(dwarf::DW_OP_LLVM_offset_uconst);
1741 OSBlock << uint8_t(dwarf::DW_OP_LLVM_user)
1742 << uint8_t(dwarf::DW_OP_LLVM_call_frame_entry_reg);
1744 OSBlock << uint8_t(dwarf::DW_OP_deref_size);
1745 OSBlock << uint8_t(Fields.MaskRegisterSizeInBits / 8);
1746 OSBlock << uint8_t(dwarf::DW_OP_LLVM_user)
1747 << uint8_t(dwarf::DW_OP_LLVM_select_bit_piece);
1751 Streamer.emitInt8(dwarf::DW_CFA_expression);
1752 Streamer.emitULEB128IntValue(Fields.Register);
1753 Streamer.emitULEB128IntValue(
Block.size());
1776 OSBlock << uint8_t(dwarf::DW_OP_LLVM_user)
1777 << uint8_t(dwarf::DW_OP_LLVM_call_frame_entry_reg);
1779 OSBlock << uint8_t(dwarf::DW_OP_deref_size)
1780 << uint8_t(Fields.MaskRegisterSizeInBits / 8);
1781 OSBlock << uint8_t(dwarf::DW_OP_LLVM_user)
1782 << uint8_t(dwarf::DW_OP_LLVM_select_bit_piece);
1786 Streamer.emitInt8(dwarf::DW_CFA_expression);
1787 Streamer.emitULEB128IntValue(Fields.Register);
1788 Streamer.emitULEB128IntValue(
Block.size());
1803 if (Label && !
Label->isDefined())
continue;
1806 if (BaseLabel && Label) {
1808 if (ThisSym != BaseLabel) {
1809 Streamer.emitDwarfAdvanceFrameAddr(BaseLabel, ThisSym,
Instr.getLoc());
1810 BaseLabel = ThisSym;
1814 emitCFIInstruction(Instr);
1846 if (!Encoding)
return;
1850 if (!DwarfEHFrameOnly && Frame.
Lsda)
1851 Encoding |= 0x40000000;
1856 Streamer.emitSymbolValue(Frame.
Begin,
Size);
1865 Streamer.emitIntValue(Encoding,
Size);
1872 Streamer.emitIntValue(0,
Size);
1876 if (!DwarfEHFrameOnly && Frame.
Lsda)
1877 Streamer.emitSymbolValue(Frame.
Lsda,
Size);
1879 Streamer.emitIntValue(0,
Size);
1885 switch (DwarfVersion) {
1898 MCContext &context = Streamer.getContext();
1903 Streamer.emitLabel(sectionStart);
1918 *sectionEnd, UnitLengthBytes);
1924 Streamer.emitIntValue(CIE_ID, OffsetSize);
1928 Streamer.emitInt8(CIEVersion);
1932 Augmentation +=
"z";
1934 Augmentation +=
"P";
1936 Augmentation +=
"L";
1937 Augmentation +=
"R";
1939 Augmentation +=
"S";
1941 Augmentation +=
"B";
1943 Augmentation +=
"G";
1944 Streamer.emitBytes(Augmentation);
1946 Streamer.emitInt8(0);
1948 if (CIEVersion >= 4) {
1953 Streamer.emitInt8(0);
1964 if (
RAReg ==
static_cast<unsigned>(INT_MAX))
1967 if (CIEVersion == 1) {
1969 "DWARF 2 encodes return_address_register in one byte");
1970 Streamer.emitInt8(
RAReg);
1972 Streamer.emitULEB128IntValue(
RAReg);
1976 unsigned augmentationLength = 0;
1980 augmentationLength += 1;
1982 augmentationLength +=
1986 augmentationLength += 1;
1988 augmentationLength += 1;
1990 Streamer.emitULEB128IntValue(augmentationLength);
2013 emitCFIInstructions(Instructions,
nullptr);
2016 InitialCFAOffset = CFAOffset;
2021 Streamer.emitLabel(sectionEnd);
2022 return *sectionStart;
2025void FrameEmitterImpl::EmitFDE(
const MCSymbol &cieStart,
2029 MCContext &context = Streamer.getContext();
2034 CFAOffset = InitialCFAOffset;
2047 Streamer.emitLabel(fdeStart);
2060 Streamer.emitSymbolValue(&cieStart, OffsetSize,
2065 unsigned PCEncoding =
2077 unsigned augmentationLength = 0;
2082 Streamer.emitULEB128IntValue(augmentationLength);
2097 Streamer.emitValueToAlignment(
Align(Alignment));
2099 Streamer.emitLabel(fdeEnd);
2107 explicit CIEKey(
const MCDwarfFrameInfo &Frame,
bool IsEH)
2108 : Personality(Frame.Personality),
2109 PersonalityEncoding(Frame.PersonalityEncoding),
2110 LsdaEncoding(Frame.LsdaEncoding), IsSignalFrame(Frame.IsSignalFrame),
2111 IsSimple(Frame.IsSimple),
RAReg(Frame.
RAReg),
2112 IsBKeyFrame(Frame.IsBKeyFrame),
2113 IsMTETaggedFrame(Frame.IsMTETaggedFrame), IsEH(IsEH) {}
2115 StringRef PersonalityName()
const {
2118 return Personality->getName();
2124 return std::make_tuple(
RAReg, IsSimple) <
2125 std::make_tuple(
Other.RAReg,
Other.IsSimple);
2127 return std::make_tuple(PersonalityName(), PersonalityEncoding, LsdaEncoding,
2128 IsSignalFrame, IsSimple,
RAReg, IsBKeyFrame,
2130 std::make_tuple(
Other.PersonalityName(),
Other.PersonalityEncoding,
2133 Other.IsMTETaggedFrame);
2141 return Personality ==
Other.Personality &&
2142 PersonalityEncoding ==
Other.PersonalityEncoding &&
2143 LsdaEncoding ==
Other.LsdaEncoding &&
2144 IsSignalFrame ==
Other.IsSignalFrame && IsSimple ==
Other.IsSimple &&
2146 IsMTETaggedFrame ==
Other.IsMTETaggedFrame;
2150 const MCSymbol *Personality =
nullptr;
2151 unsigned PersonalityEncoding = 0;
2152 unsigned LsdaEncoding = -1;
2153 bool IsSignalFrame =
false;
2154 bool IsSimple =
false;
2155 unsigned RAReg = UINT_MAX;
2156 bool IsBKeyFrame =
false;
2157 bool IsMTETaggedFrame =
false;
2166 const MCAsmInfo &AsmInfo = Context.getAsmInfo();
2167 FrameEmitterImpl
Emitter(IsEH, Streamer);
2174 bool SectionEmitted =
false;
2177 if (!SectionEmitted) {
2180 SectionEmitted =
true;
2182 NeedsEHFrameSection |=
2185 Emitter.EmitCompactUnwind(Frame);
2193 if (!NeedsEHFrameSection && IsEH)
return;
2200 MCSymbol *SectionStart = Context.createTempSymbol();
2208 std::vector<MCDwarfFrameInfo> FrameArrayX(FrameArray.
begin(), FrameArray.
end());
2211 return CIEKey(
X, IsEH) < CIEKey(
Y, IsEH);
2214 const MCSymbol *LastCIEStart =
nullptr;
2215 for (
auto I = FrameArrayX.begin(), E = FrameArrayX.end();
I != E;) {
2228 CIEKey
Key(Frame, IsEH);
2229 if (!LastCIEStart ||
Key != LastKey) {
2231 LastCIEStart = &
Emitter.EmitCIE(Frame);
2234 Emitter.EmitFDE(*LastCIEStart, Frame,
I == E, *SectionStart);
2251 uint8_t Opcode = dwarf::DW_CFA_advance_loc | AddrDelta;
2254 Out.
push_back(dwarf::DW_CFA_advance_loc1);
2257 Out.
push_back(dwarf::DW_CFA_advance_loc2);
2261 Out.
push_back(dwarf::DW_CFA_advance_loc4);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
dxil DXContainer Global Emitter
This file contains constants used for implementing Dwarf debug support.
static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol, unsigned symbolEncoding, bool isEH)
static uint64_t SpecialAddr(MCDwarfLineTableParams Params, uint64_t op)
Given a special op, return the address skip amount (in units of DWARF2_LINE_MIN_INSN_LENGTH).
static void EmitGenDwarfAranges(MCStreamer *MCOS, const MCSymbol *InfoSectionSymbol)
static bool isRootFile(const MCDwarfFile &RootFile, StringRef &Directory, StringRef &FileName, std::optional< MD5::MD5Result > Checksum)
static uint64_t ScaleAddrDelta(MCContext &Context, uint64_t AddrDelta)
static const MCExpr * forceExpAbs(MCStreamer &OS, const MCExpr *Expr)
static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size)
static void encodeDwarfRegisterLocation(int DwarfReg, raw_ostream &OS)
static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile, bool EmitMD5, bool HasAnySource, std::optional< MCDwarfLineStr > &LineStr)
static const MCExpr * makeEndMinusStartExpr(MCContext &Ctx, const MCSymbol &Start, const MCSymbol &End, int IntVal)
static unsigned getCIEVersion(bool IsEH, unsigned DwarfVersion)
static void EmitGenDwarfInfo(MCStreamer *MCOS, const MCSymbol *AbbrevSectionSymbol, const MCSymbol *LineSectionSymbol, const MCSymbol *RangesSymbol)
static void EmitAbbrev(MCStreamer *MCOS, uint64_t Name, uint64_t Form)
static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, unsigned symbolEncoding)
static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding)
static int getDataAlignmentFactor(MCStreamer &streamer)
static MCSymbol * emitGenDwarfRanges(MCStreamer *MCOS)
static const MCExpr * makeStartPlusIntExpr(MCContext &Ctx, const MCSymbol &Start, int IntVal)
static void EmitGenDwarfAbbrev(MCStreamer *MCOS)
static unsigned getSizeForEncoding(MCStreamer &streamer, unsigned symbolEncoding)
#define DWARF2_FLAG_IS_STMT
#define DWARF2_FLAG_BASIC_BLOCK
#define DWARF2_LINE_DEFAULT_IS_STMT
#define DWARF2_FLAG_PROLOGUE_END
#define DWARF2_FLAG_EPILOGUE_BEGIN
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr MCPhysReg RAReg
This file defines the SmallString class.
This file defines the SmallVector class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Tagged union holding either a T or a Error.
This class is intended to be used as a base class for asm properties and features specific to the tar...
unsigned getMinInstAlignment() const
const std::vector< MCCFIInstruction > & getInitialFrameState() const
bool needsDwarfSectionOffsetDirective() const
bool doesDwarfUseRelocationsAcrossSections() const
const MCExpr * getExprForFDESymbol(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const
bool isStackGrowthDirectionUp() const
True if target stack grow up.
unsigned getCalleeSaveStackSlotSize() const
Get the callee-saved register stack slot size in bytes.
bool doDwarfFDESymbolsUseAbsDiff() const
virtual const MCExpr * getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const
unsigned getCodePointerSize() const
Get the code pointer size in bytes.
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCBinaryExpr * create(Opcode Op, const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
LLVM_ABI void replaceRegister(unsigned FromReg, unsigned ToReg)
Replaces in place all references to FromReg with ToReg.
@ OpLLVMVectorRegisterMask
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
const MCObjectFileInfo * getObjectFileInfo() const
LLVM_ABI void remapDebugPath(SmallVectorImpl< char > &Path)
Remap one path in-place as per the debug prefix map.
const SetVector< MCSection * > & getGenDwarfSectionSyms()
const SmallVectorImpl< std::string > & getMCDwarfDirs(unsigned CUID=0)
StringRef getDwarfDebugProducer()
StringRef getDwarfDebugFlags()
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
StringRef getCompilationDir() const
Get the compilation directory for DW_AT_comp_dir The compilation directory should be set with setComp...
MCDwarfLineTable & getMCDwarfLineTable(unsigned CUID)
unsigned getDwarfCompileUnitID()
const MCRegisterInfo * getRegisterInfo() const
const SmallVectorImpl< MCDwarfFile > & getMCDwarfFiles(unsigned CUID=0)
const std::map< unsigned, MCDwarfLineTable > & getMCDwarfLineTables() const
unsigned getGenDwarfFileNumber()
uint16_t getDwarfVersion() const
LLVM_ABI void finalizeDwarfSections(MCStreamer &MCOS)
Remove empty sections from SectionsForRanges, to avoid generating useless debug info for them.
void addMCGenDwarfLabelEntry(const MCGenDwarfLabelEntry &E)
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
const MCDwarfLoc & getCurrentDwarfLoc()
dwarf::DwarfFormat getDwarfFormat() const
const MCAsmInfo & getAsmInfo() const
const std::vector< MCGenDwarfLabelEntry > & getMCGenDwarfLabelEntries() const
LLVM_ABI void Emit(MCStreamer &MCOS, MCDwarfLineTableParams Params, MCSection *Section) const
static LLVM_ABI void emit(MCObjectStreamer &streamer, bool isEH)
static LLVM_ABI void encodeAdvanceLoc(MCContext &Context, uint64_t AddrDelta, SmallVectorImpl< char > &OS)
static LLVM_ABI void Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, int64_t LineDelta, uint64_t AddrDelta)
Utility function to emit the encoding to a streamer.
static LLVM_ABI void encode(MCContext &Context, MCDwarfLineTableParams Params, int64_t LineDelta, uint64_t AddrDelta, SmallVectorImpl< char > &OS)
Utility function to encode a Dwarf pair of LineDelta and AddrDeltas.
Instances of this class represent the line information for the dwarf line table entries.
void setEndLabel(MCSymbol *EndLabel)
MCDwarfLineEntry(MCSymbol *label, const MCDwarfLoc loc, MCSymbol *lineStreamLabel=nullptr, SMLoc streamLabelDefLoc={})
MCSymbol * LineStreamLabel
static LLVM_ABI void make(MCStreamer *MCOS, MCSection *Section)
LLVM_ABI void emitSection(MCStreamer *MCOS)
Emit the .debug_line_str section if appropriate.
LLVM_ABI MCDwarfLineStr(MCContext &Ctx)
Construct an instance that can emit .debug_line_str (for use in a normal v5 line table).
LLVM_ABI SmallString< 0 > getFinalizedData()
Returns finalized section.
LLVM_ABI void emitRef(MCStreamer *MCOS, StringRef Path)
Emit a reference to the string.
LLVM_ABI size_t addString(StringRef Path)
Adds path Path to the line string.
LLVM_ABI void endCurrentSeqAndEmitLineStreamLabel(MCStreamer *MCOS, SMLoc DefLoc, StringRef Name)
MCDwarfFile & getRootFile()
const MCLineSection & getMCLineSections() const
static LLVM_ABI void emit(MCStreamer *MCOS, MCDwarfLineTableParams Params)
static LLVM_ABI void emitOne(MCStreamer *MCOS, MCSection *Section, const MCLineSection::MCDwarfLineEntryCollection &LineEntries)
LLVM_ABI Expected< unsigned > tryGetFile(StringRef &Directory, StringRef &FileName, std::optional< MD5::MD5Result > Checksum, std::optional< StringRef > Source, uint16_t DwarfVersion, unsigned FileNumber=0)
LLVM_ABI void emitCU(MCStreamer *MCOS, MCDwarfLineTableParams Params, std::optional< MCDwarfLineStr > &LineStr) const
Instances of this class represent the information from a dwarf .loc directive.
Base class for the full range of assembler expressions which are needed for parsing.
static LLVM_ABI void Emit(MCStreamer *MCOS)
MCGenDwarfLabelEntry(StringRef name, unsigned fileNumber, unsigned lineNumber, MCSymbol *label)
static LLVM_ABI void Make(MCSymbol *Symbol, MCStreamer *MCOS, SourceMgr &SrcMgr, SMLoc &Loc)
LLVM_ABI void addEndEntry(MCSymbol *EndLabel)
void addLineEntry(const MCDwarfLineEntry &LineEntry, MCSection *Sec)
std::vector< MCDwarfLineEntry > MCDwarfLineEntryCollection
MCSection * getDwarfRangesSection() const
bool getSupportsCompactUnwindWithoutEHFrame() const
MCSection * getDwarfLineStrSection() const
unsigned getCompactUnwindDwarfEHFrameOnly() const
MCSection * getDwarfRnglistsSection() const
MCSection * getDwarfLineSection() const
MCSection * getDwarfInfoSection() const
MCSection * getDwarfFrameSection() const
unsigned getFDEEncoding() const
MCSection * getDwarfAbbrevSection() const
bool getOmitDwarfIfHaveCompactUnwind() const
MCSection * getDwarfARangesSection() const
MCSection * getCompactUnwindSection() const
Streaming object file generation interface.
void generateCompactUnwindEncodings()
void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0) override
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
MCRegister getRARegister() const
This method should return the register where the return address can be found.
virtual int64_t getDwarfRegNum(MCRegister Reg, bool isEH) const
Map a target register to an equivalent dwarf register number.
Instances of this class represent a uniqued identifier for a section in the current translation unit.
MCSymbol * getBeginSymbol()
Streaming machine code generation interface.
virtual void emitAssignment(MCSymbol *Symbol, const MCExpr *Value)
Emit an assignment of Value to Symbol.
virtual void emitBinaryData(StringRef Data)
Functionally identical to EmitBytes.
virtual void emitDwarfUnitLength(uint64_t Length, const Twine &Comment)
Emit a unit length field.
MCContext & getContext() const
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
virtual void emitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset)
Emits a COFF section relative relocation.
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
void emitSymbolValue(const MCSymbol *Sym, unsigned Size, bool IsSectionRelative=false)
Special case of EmitValue that avoids the client having to pass in a MCExpr for MCSymbols.
virtual void emitDwarfLineStartLabel(MCSymbol *StartSym)
Emit the debug line start label.
virtual void emitAbsoluteSymbolDiff(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size)
Emit the absolute difference between two symbols.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
virtual void emitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, unsigned PointerSize)
If targets does not support representing debug line section by .loc/.file directives in assembly outp...
void emitInt16(uint64_t Value)
virtual MCSymbol * getDwarfLineTableSymbol(unsigned CUID)
unsigned emitULEB128IntValue(uint64_t Value, unsigned PadTo=0)
Special case of EmitULEB128Value that avoids the client having to pass in a MCExpr for constant integ...
virtual void emitULEB128Value(const MCExpr *Value)
ArrayRef< MCDwarfFrameInfo > getDwarfFrameInfos() const
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
void emitInt32(uint64_t Value)
MCSection * getCurrentSectionOnly() const
virtual void emitDwarfLineEndEntry(MCSection *Section, MCSymbol *LastLabel, MCSymbol *EndLabel=nullptr)
Emit the debug line end entry.
void emitInt8(uint64_t Value)
void emitFill(uint64_t NumBytes, uint8_t FillValue)
Emit NumBytes bytes worth of the value specified by FillValue.
virtual void emitBytes(StringRef Data)
Emit the bytes in Data into the output.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
Wrapper class representing virtual and physical registers.
Represents a location in source code.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Represent a constant reference to a string, i.e.
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
constexpr bool empty() const
Check if the string is empty.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const uint32_t DW_CIE_ID
Special ID values that distinguish a CIE from a FDE in DWARF CFI.
uint8_t getUnitLengthFieldByteSize(DwarfFormat Format)
Get the byte size of the unit length field depending on the DWARF format.
const uint64_t DW64_CIE_ID
DwarfFormat
Constants that define the DWARF format as 32 or 64 bit.
uint8_t getDwarfOffsetByteSize(DwarfFormat Format)
The size of a reference determined by the DWARF 32/64-bit format.
@ DW_LENGTH_DWARF64
Indicator of 64-bit DWARF format.
LLVM_ABI MCSymbol * emitListsTableHeaderStart(MCStreamer &S)
NodeAddr< InstrNode * > Instr
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
LLVM_ABI StringRef get_separator(Style style=Style::native)
Return the preferred separator for this platform.
LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
This is an optimization pass for GlobalISel generic memory operations.
bool operator<(int64_t V1, const APSInt &V2)
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
bool operator!=(uint64_t V1, const APInt &V2)
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI SourceMgr SrcMgr
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
ArrayRef(const T &OneElt) -> ArrayRef< T >
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
void appendLEB128(SmallVectorImpl< U > &Buffer, T Value)
constexpr decltype(auto) makeVisitor(CallableTs &&...Callables)
Returns an opaquely-typed Callable object whose operator() overload set is the sum of the operator() ...
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Held in ExtraFields when OpLLVMSetRAState.
Held in ExtraFields when OpLLVMRegisterPair.
Held in ExtraFields when OpLLVMVectorOffset.
Held in ExtraFields when OpLLVMVectorRegisterMask.
Held in ExtraFields when OpLLVMVectorRegisters.
std::vector< VectorRegisterWithLane > VectorRegisters
Instances of this class represent the name of the dwarf .file directive and its associated dwarf file...
std::optional< MD5::MD5Result > Checksum
The MD5 checksum, if there is one.
const MCSymbol * Personality
unsigned PersonalityEncoding
uint64_t CompactUnwindEncoding
std::vector< MCCFIInstruction > Instructions
uint8_t DWARF2LineOpcodeBase
First special line opcode - leave room for the standard opcodes.
uint8_t DWARF2LineRange
Range of line offsets in a special line info. opcode.
int8_t DWARF2LineBase
Minimum line offset in a special line info.