36 std::unique_ptr<DwarfStreamer> Streamer =
37 std::make_unique<DwarfStreamer>(FileType, OutFile,
Warning);
38 if (
Error Err = Streamer->init(TheTriple,
"__DWARF"))
39 return std::move(Err);
41 return std::move(Streamer);
47 std::string TripleName;
61 "no register info for target %s",
65 MCOptions.AsmVerbose =
true;
70 "no asm info for target %s", TripleName.c_str());
75 "no subtarget info for target %s",
78 MC.reset(
new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(),
nullptr,
79 true, Swift5ReflectionSegmentName));
81 MC->setObjectFileInfo(MOFI.get());
86 "no asm backend for target %s",
92 "no instr info info for target %s",
98 "no code emitter for target %s",
101 switch (OutFileType) {
104 TheTriple, MAI->getAssemblerDialect(), *MAI, *MII, *MRI));
106 *MC, std::make_unique<formatted_raw_ostream>(OutFile), std::move(MIP),
107 std::unique_ptr<MCCodeEmitter>(MCE),
108 std::unique_ptr<MCAsmBackend>(MAB));
113 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
114 MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
122 "no object streamer for target %s",
130 "no target machine for target %s",
133 Asm.reset(TheTarget->
createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
136 "no asm printer for target %s",
138 Asm->setDwarfUsesRelocationsAcrossSections(
false);
140 RangesSectionSize = 0;
141 RngListsSectionSize = 0;
143 LocListsSectionSize = 0;
145 FrameSectionSize = 0;
146 DebugInfoSectionSize = 0;
147 MacInfoSectionSize = 0;
148 MacroSectionSize = 0;
156 MS->switchSection(MOFI->getDwarfInfoSection());
157 MC->setDwarfVersion(DwarfVersion);
177 unsigned DwarfVersion) {
181 Unit.setLabelBegin(Asm->createTempSymbol(
"cu_begin"));
182 Asm->OutStreamer->emitLabel(Unit.getLabelBegin());
187 Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
188 Asm->emitInt16(DwarfVersion);
190 if (DwarfVersion >= 5) {
191 Asm->emitInt8(dwarf::DW_UT_compile);
192 Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
196 DebugInfoSectionSize += 12;
201 Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
202 DebugInfoSectionSize += 11;
206 EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()});
212 const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
213 unsigned DwarfVersion) {
214 MS->switchSection(MOFI->getDwarfAbbrevSection());
215 MC->setDwarfVersion(DwarfVersion);
216 Asm->emitDwarfAbbrevs(Abbrevs);
221 MS->switchSection(MOFI->getDwarfInfoSection());
222 Asm->emitDwarfDIE(Die);
223 DebugInfoSectionSize += Die.
getSize();
232 if (
MCSection *Section = getMCSection(SecKind)) {
233 MS->switchSection(Section);
235 MS->emitBytes(SecData);
242 return MC->getObjectFileInfo()->getDwarfInfoSection();
244 return MC->getObjectFileInfo()->getDwarfLineSection();
246 return MC->getObjectFileInfo()->getDwarfFrameSection();
248 return MC->getObjectFileInfo()->getDwarfRangesSection();
250 return MC->getObjectFileInfo()->getDwarfRnglistsSection();
252 return MC->getObjectFileInfo()->getDwarfLocSection();
254 return MC->getObjectFileInfo()->getDwarfLoclistsSection();
256 return MC->getObjectFileInfo()->getDwarfARangesSection();
258 return MC->getObjectFileInfo()->getDwarfAbbrevSection();
260 return MC->getObjectFileInfo()->getDwarfMacinfoSection();
262 return MC->getObjectFileInfo()->getDwarfMacroSection();
264 return MC->getObjectFileInfo()->getDwarfAddrSection();
266 return MC->getObjectFileInfo()->getDwarfStrSection();
268 return MC->getObjectFileInfo()->getDwarfLineStrSection();
270 return MC->getObjectFileInfo()->getDwarfStrOffSection();
272 return MC->getObjectFileInfo()->getDwarfPubNamesSection();
274 return MC->getObjectFileInfo()->getDwarfPubTypesSection();
276 return MC->getObjectFileInfo()->getDwarfDebugNamesSection();
278 return MC->getObjectFileInfo()->getDwarfAccelNamesSection();
280 return MC->getObjectFileInfo()->getDwarfAccelNamespaceSection();
282 return MC->getObjectFileInfo()->getDwarfAccelObjCSection();
284 return MC->getObjectFileInfo()->getDwarfAccelTypesSection();
295 Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());
297 for (
auto Entry : Entries) {
299 Asm->OutStreamer->emitBytes(Entry.getString());
310 if (TargetDWARFVersion < 5 || StringOffsets.
empty())
313 Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection());
315 MCSymbol *BeginLabel = Asm->createTempSymbol(
"Bdebugstroff");
316 MCSymbol *EndLabel = Asm->createTempSymbol(
"Edebugstroff");
319 Asm->emitLabelDifference(EndLabel, BeginLabel,
sizeof(
uint32_t));
320 Asm->OutStreamer->emitLabel(BeginLabel);
321 StrOffsetSectionSize +=
sizeof(
uint32_t);
325 StrOffsetSectionSize +=
sizeof(
uint16_t);
329 StrOffsetSectionSize +=
sizeof(
uint16_t);
331 for (
auto Off : StringOffsets) {
332 Asm->OutStreamer->emitInt32(Off);
333 StrOffsetSectionSize +=
sizeof(
uint32_t);
335 Asm->OutStreamer->emitLabel(EndLabel);
340 Asm->OutStreamer->switchSection(MOFI->getDwarfLineStrSection());
342 for (
auto Entry : Entries) {
344 Asm->OutStreamer->emitBytes(Entry.getString());
351 if (EmittedUnits.empty())
355 std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
358 for (
auto &
CU : EmittedUnits) {
359 CompUnits.push_back(
CU.LabelBegin);
361 UniqueIdToCuMap[
CU.ID] = Id++;
364 Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
371 Asm.get(), Table, CompUnits,
373 -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {
374 if (UniqueIdToCuMap.size() > 1)
375 return {{UniqueIdToCuMap[Entry.getUnitID()],
376 {dwarf::DW_IDX_compile_unit, Form}}};
383 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
384 auto *SectionBegin = Asm->createTempSymbol(
"namespac_begin");
385 Asm->OutStreamer->emitLabel(SectionBegin);
391 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
392 auto *SectionBegin = Asm->createTempSymbol(
"names_begin");
393 Asm->OutStreamer->emitLabel(SectionBegin);
399 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
400 auto *SectionBegin = Asm->createTempSymbol(
"objc_begin");
401 Asm->OutStreamer->emitLabel(SectionBegin);
407 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
408 auto *SectionBegin = Asm->createTempSymbol(
"types_begin");
409 Asm->OutStreamer->emitLabel(SectionBegin);
415 MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
417 MS->switchSection(SwiftASTSection);
418 MS->emitBytes(Buffer);
425 MOFI->getSwift5ReflectionSection(ReflSectionKind);
426 if (ReflectionSection ==
nullptr)
429 MS->switchSection(ReflectionSection);
430 MS->emitBytes(Buffer);
435 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
438 MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
441 MCSymbol *BeginLabel = Asm->createTempSymbol(
"Barange");
442 MCSymbol *EndLabel = Asm->createTempSymbol(
"Earange");
444 unsigned HeaderSize =
451 unsigned TupleSize = AddressSize * 2;
454 Asm->emitLabelDifference(EndLabel, BeginLabel, 4);
455 Asm->OutStreamer->emitLabel(BeginLabel);
457 Asm->emitInt32(Unit.getStartOffset());
458 Asm->emitInt8(AddressSize);
461 Asm->OutStreamer->emitFill(Padding, 0x0);
465 MS->emitIntValue(
Range.start(), AddressSize);
466 MS->emitIntValue(
Range.end() -
Range.start(), AddressSize);
470 Asm->OutStreamer->emitIntValue(0, AddressSize);
471 Asm->OutStreamer->emitIntValue(0, AddressSize);
472 Asm->OutStreamer->emitLabel(EndLabel);
475Error DwarfStreamer::emitDwarfDebugRangesTableFragment(
479 RangesSectionSize, Unit.getOrigUnit().getFormParams(),
".debug_ranges");
481 return Offset.takeError();
485 MS->
switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
486 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
490 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
491 BaseAddress = *LowPC;
497 RangesSectionSize += AddressSize;
498 RangesSectionSize += AddressSize;
505 RangesSectionSize += AddressSize;
506 RangesSectionSize += AddressSize;
512 if (Unit.getOrigUnit().getVersion() < 5)
516 MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
518 MCSymbol *BeginLabel = Asm->createTempSymbol(
"Brnglists");
519 MCSymbol *EndLabel = Asm->createTempSymbol(
"Ernglists");
520 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
523 Asm->emitLabelDifference(EndLabel, BeginLabel,
sizeof(
uint32_t));
524 Asm->OutStreamer->emitLabel(BeginLabel);
525 RngListsSectionSize +=
sizeof(
uint32_t);
529 RngListsSectionSize +=
sizeof(
uint16_t);
532 MS->emitInt8(AddressSize);
533 RngListsSectionSize++;
537 RngListsSectionSize++;
541 RngListsSectionSize +=
sizeof(
uint32_t);
549 if (Unit.getOrigUnit().getVersion() < 5) {
550 return emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch);
553 return emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch,
559 if (Unit.getOrigUnit().getVersion() < 5)
563 MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
565 if (EndLabel !=
nullptr)
566 Asm->OutStreamer->emitLabel(EndLabel);
569Error DwarfStreamer::emitDwarfDebugRngListsTableFragment(
573 clampSecOffset(RngListsSectionSize, Unit.getOrigUnit().getFormParams(),
576 return Offset.takeError();
580 MS->
switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
581 std::optional<uint64_t> BaseAddress;
586 BaseAddress =
Range.start();
589 MS->
emitInt8(dwarf::DW_RLE_base_addressx);
590 RngListsSectionSize += 1;
591 RngListsSectionSize +=
596 MS->
emitInt8(dwarf::DW_RLE_offset_pair);
597 RngListsSectionSize += 1;
600 RngListsSectionSize +=
608 MS->
emitInt8(dwarf::DW_RLE_end_of_list);
609 RngListsSectionSize += 1;
615 if (Unit.getOrigUnit().getVersion() < 5)
619 MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
621 MCSymbol *BeginLabel = Asm->createTempSymbol(
"Bloclists");
622 MCSymbol *EndLabel = Asm->createTempSymbol(
"Eloclists");
623 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
626 Asm->emitLabelDifference(EndLabel, BeginLabel,
sizeof(
uint32_t));
627 Asm->OutStreamer->emitLabel(BeginLabel);
628 LocListsSectionSize +=
sizeof(
uint32_t);
632 LocListsSectionSize +=
sizeof(
uint16_t);
635 MS->emitInt8(AddressSize);
636 LocListsSectionSize++;
640 LocListsSectionSize++;
644 LocListsSectionSize +=
sizeof(
uint32_t);
654 if (Unit.getOrigUnit().getVersion() < 5) {
655 return emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression,
659 return emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression,
666 if (Unit.getOrigUnit().getVersion() < 5)
670 MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
672 if (EndLabel !=
nullptr)
673 Asm->OutStreamer->emitLabel(EndLabel);
677Error DwarfStreamer::emitDwarfDebugLocTableFragment(
682 LocSectionSize, Unit.getOrigUnit().getFormParams(),
".debug_loc");
684 return Offset.takeError();
688 MS->
switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
689 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
693 if (std::optional<uint64_t> LowPC = Unit.getLowPc())
694 BaseAddress = *LowPC;
697 LinkedLocationExpression) {
698 if (LocExpression.Range) {
699 MS->
emitIntValue(LocExpression.Range->LowPC - BaseAddress, AddressSize);
700 MS->
emitIntValue(LocExpression.Range->HighPC - BaseAddress, AddressSize);
702 LocSectionSize += AddressSize;
703 LocSectionSize += AddressSize;
706 Asm->OutStreamer->emitIntValue(LocExpression.Expr.size(), 2);
708 (
const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
709 LocSectionSize += LocExpression.Expr.size() + 2;
716 LocSectionSize += AddressSize;
717 LocSectionSize += AddressSize;
725 MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection());
727 MCSymbol *BeginLabel = Asm->createTempSymbol(
"Bdebugaddr");
728 MCSymbol *EndLabel = Asm->createTempSymbol(
"Edebugaddr");
729 unsigned AddrSize = Unit.getOrigUnit().getAddressByteSize();
732 Asm->emitLabelDifference(EndLabel, BeginLabel,
sizeof(
uint32_t));
733 Asm->OutStreamer->emitLabel(BeginLabel);
734 AddrSectionSize +=
sizeof(
uint32_t);
738 AddrSectionSize += 2;
741 Asm->emitInt8(AddrSize);
742 AddrSectionSize += 1;
746 AddrSectionSize += 1;
754 Asm->OutStreamer->switchSection(MOFI->getDwarfAddrSection());
755 for (
auto Addr : Addrs) {
756 Asm->OutStreamer->emitIntValue(Addr, AddrSize);
757 AddrSectionSize += AddrSize;
766 MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection());
768 if (EndLabel !=
nullptr)
769 Asm->OutStreamer->emitLabel(EndLabel);
773Error DwarfStreamer::emitDwarfDebugLocListsTableFragment(
778 clampSecOffset(LocListsSectionSize, Unit.getOrigUnit().getFormParams(),
781 return Offset.takeError();
785 MS->
switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
786 std::optional<uint64_t> BaseAddress;
789 LinkedLocationExpression) {
790 if (LocExpression.Range) {
794 BaseAddress = LocExpression.Range->LowPC;
797 MS->
emitInt8(dwarf::DW_LLE_base_addressx);
798 LocListsSectionSize += 1;
799 LocListsSectionSize +=
804 MS->
emitInt8(dwarf::DW_LLE_offset_pair);
805 LocListsSectionSize += 1;
808 LocListsSectionSize +=
812 LocListsSectionSize +=
816 MS->
emitInt8(dwarf::DW_LLE_default_location);
817 LocListsSectionSize += 1;
822 (
const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
823 LocListsSectionSize += LocExpression.Expr.size();
827 MS->emitInt8(dwarf::DW_LLE_end_of_list);
828 LocListsSectionSize += 1;
835 std::vector<uint64_t> *RowOffsets) {
837 MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
839 MCSymbol *LineStartSym = MC->createTempSymbol();
840 MCSymbol *LineEndSym = MC->createTempSymbol();
845 LineSectionSize += 4;
847 emitLabelDifference(LineEndSym, LineStartSym,
849 Asm->OutStreamer->emitLabel(LineStartSym);
852 emitLineTablePrologue(LineTable.
Prologue, DebugStrPool, DebugLineStrPool);
855 emitLineTableRows(LineTable, LineEndSym,
856 Unit.getOrigUnit().getAddressByteSize(), RowOffsets);
862 MCSymbol *PrologueStartSym = MC->createTempSymbol();
863 MCSymbol *PrologueEndSym = MC->createTempSymbol();
867 LineSectionSize += 2;
868 if (
P.getVersion() == 5) {
871 LineSectionSize += 1;
875 LineSectionSize += 1;
879 emitLabelDifference(PrologueEndSym, PrologueStartSym,
P.FormParams.Format,
882 Asm->OutStreamer->emitLabel(PrologueStartSym);
883 emitLineTableProloguePayload(
P, DebugStrPool, DebugLineStrPool);
884 Asm->OutStreamer->emitLabel(PrologueEndSym);
887void DwarfStreamer::emitLineTablePrologueV2IncludeAndFileTable(
892 emitLineTableString(
P,
Include, DebugStrPool, DebugLineStrPool);
895 LineSectionSize += 1;
901 emitLineTableString(
P, File.Name, DebugStrPool, DebugLineStrPool);
914 LineSectionSize += 1;
917void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable(
920 if (
P.IncludeDirectories.empty()) {
923 LineSectionSize += 1;
927 LineSectionSize += 1;
930 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);
932 MS->emitULEB128IntValue(
P.IncludeDirectories[0].getForm());
936 LineSectionSize += MS->emitULEB128IntValue(
P.IncludeDirectories.size());
938 for (
auto Include :
P.IncludeDirectories)
939 emitLineTableString(
P,
Include, DebugStrPool, DebugLineStrPool);
941 bool HasChecksums =
P.ContentTypes.HasMD5;
942 bool HasInlineSources =
P.ContentTypes.HasSource;
944 if (
P.FileNames.empty()) {
947 LineSectionSize += 1;
950 MS->emitInt8(2 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0));
951 LineSectionSize += 1;
954 auto StrForm =
P.FileNames[0].Name.getForm();
955 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);
956 LineSectionSize += MS->emitULEB128IntValue(StrForm);
958 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
959 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_udata);
962 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
963 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data16);
966 if (HasInlineSources) {
967 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
968 LineSectionSize += MS->emitULEB128IntValue(StrForm);
973 LineSectionSize += MS->emitULEB128IntValue(
P.FileNames.size());
976 for (
auto File :
P.FileNames) {
977 emitLineTableString(
P,
File.Name, DebugStrPool, DebugLineStrPool);
978 LineSectionSize += MS->emitULEB128IntValue(
File.DirIdx);
981 StringRef(
reinterpret_cast<const char *
>(
File.Checksum.data()),
982 File.Checksum.size()));
983 LineSectionSize +=
File.Checksum.size();
985 if (HasInlineSources)
986 emitLineTableString(
P,
File.Source, DebugStrPool, DebugLineStrPool);
990void DwarfStreamer::emitLineTableString(
const DWARFDebugLine::Prologue &
P,
991 const DWARFFormValue &
String,
996 warn(
"Cann't read string from line table.");
1000 switch (
String.getForm()) {
1001 case dwarf::DW_FORM_string: {
1002 StringRef Str = *StringVal;
1003 Asm->OutStreamer->emitBytes(Str.data());
1005 LineSectionSize += Str.size() + 1;
1007 case dwarf::DW_FORM_strp:
1008 case dwarf::DW_FORM_line_strp: {
1009 DwarfStringPoolEntryRef StringRef =
1010 String.getForm() == dwarf::DW_FORM_strp
1011 ? DebugStrPool.
getEntry(*StringVal)
1012 : DebugLineStrPool.
getEntry(*StringVal);
1014 emitIntOffset(StringRef.
getOffset(),
P.FormParams.Format, LineSectionSize);
1017 warn(
"Unsupported string form inside line table.");
1022void DwarfStreamer::emitLineTableProloguePayload(
1026 MS->emitInt8(
P.MinInstLength);
1027 LineSectionSize += 1;
1028 if (
P.FormParams.Version >= 4) {
1030 MS->emitInt8(
P.MaxOpsPerInst);
1031 LineSectionSize += 1;
1034 MS->emitInt8(
P.DefaultIsStmt);
1035 LineSectionSize += 1;
1037 MS->emitInt8(
P.LineBase);
1038 LineSectionSize += 1;
1040 MS->emitInt8(
P.LineRange);
1041 LineSectionSize += 1;
1043 MS->emitInt8(
P.OpcodeBase);
1044 LineSectionSize += 1;
1047 for (
auto Length :
P.StandardOpcodeLengths) {
1049 LineSectionSize += 1;
1052 if (
P.FormParams.Version < 5)
1053 emitLineTablePrologueV2IncludeAndFileTable(
P, DebugStrPool,
1056 emitLineTablePrologueV5IncludeAndFileTable(
P, DebugStrPool,
1060void DwarfStreamer::emitLineTableRows(
1061 const DWARFDebugLine::LineTable &LineTable, MCSymbol *LineEndSym,
1062 unsigned AddressByteSize, std::vector<uint64_t> *RowOffsets) {
1064 MCDwarfLineTableParams Params;
1069 SmallString<128> EncodingBuffer;
1071 if (LineTable.
Rows.empty()) {
1076 MS->emitBytes(EncodingBuffer);
1077 LineSectionSize += EncodingBuffer.
size();
1078 MS->emitLabel(LineEndSym);
1083 unsigned FileNum = 1;
1084 unsigned LastLine = 1;
1085 unsigned Column = 0;
1087 unsigned IsStatement = 1;
1091 unsigned RowsSinceLastSequence = 0;
1093 for (
const DWARFDebugLine::Row &Row : LineTable.
Rows) {
1097 RowOffsets->push_back(LineSectionSize);
1101 MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);
1102 MS->emitULEB128IntValue(AddressByteSize + 1);
1103 MS->emitIntValue(dwarf::DW_LNE_set_address, 1);
1104 MS->emitIntValue(Row.Address.Address, AddressByteSize);
1118 if (FileNum != Row.File) {
1120 MS->emitIntValue(dwarf::DW_LNS_set_file, 1);
1121 MS->emitULEB128IntValue(FileNum);
1124 if (Column != Row.Column) {
1125 Column = Row.Column;
1126 MS->emitIntValue(dwarf::DW_LNS_set_column, 1);
1127 MS->emitULEB128IntValue(Column);
1130 if (Discriminator != Row.Discriminator &&
1131 MS->getContext().getDwarfVersion() >= 4) {
1134 MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);
1135 MS->emitULEB128IntValue(
Size + 1);
1136 MS->emitIntValue(dwarf::DW_LNE_set_discriminator, 1);
1137 MS->emitULEB128IntValue(Discriminator);
1143 if (Isa != Row.Isa) {
1145 MS->emitIntValue(dwarf::DW_LNS_set_isa, 1);
1146 MS->emitULEB128IntValue(Isa);
1149 if (IsStatement != Row.IsStmt) {
1150 IsStatement = Row.IsStmt;
1151 MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1);
1152 LineSectionSize += 1;
1154 if (Row.BasicBlock) {
1155 MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1);
1156 LineSectionSize += 1;
1159 if (Row.PrologueEnd) {
1160 MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
1161 LineSectionSize += 1;
1164 if (Row.EpilogueBegin) {
1165 MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
1166 LineSectionSize += 1;
1169 int64_t LineDelta = int64_t(Row.Line) - LastLine;
1170 if (!Row.EndSequence) {
1173 MS->emitBytes(EncodingBuffer);
1174 LineSectionSize += EncodingBuffer.
size();
1175 EncodingBuffer.
resize(0);
1176 Address = Row.Address.Address;
1177 LastLine = Row.Line;
1178 RowsSinceLastSequence++;
1181 MS->emitIntValue(dwarf::DW_LNS_advance_line, 1);
1182 MS->emitSLEB128IntValue(LineDelta);
1186 MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1);
1192 MS->emitBytes(EncodingBuffer);
1193 LineSectionSize += EncodingBuffer.
size();
1194 EncodingBuffer.
resize(0);
1196 LastLine = FileNum = IsStatement = 1;
1201 if (RowsSinceLastSequence) {
1204 MS->emitBytes(EncodingBuffer);
1205 LineSectionSize += EncodingBuffer.
size();
1206 EncodingBuffer.
resize(0);
1209 MS->emitLabel(LineEndSym);
1213 uint64_t &SectionSize) {
1219void DwarfStreamer::emitLabelDifference(
const MCSymbol *
Hi,
const MCSymbol *
Lo,
1221 uint64_t &SectionSize) {
1223 Asm->emitLabelDifference(
Hi,
Lo,
Size);
1229void DwarfStreamer::emitPubSectionForUnit(
1230 MCSection *Sec, StringRef SecName,
const CompileUnit &Unit,
1231 const std::vector<CompileUnit::AccelInfo> &Names) {
1236 Asm->OutStreamer->switchSection(Sec);
1237 MCSymbol *BeginLabel = Asm->createTempSymbol(
"pub" + SecName +
"_begin");
1238 MCSymbol *EndLabel = Asm->createTempSymbol(
"pub" + SecName +
"_end");
1240 bool HeaderEmitted =
false;
1242 for (
const auto &Name : Names) {
1243 if (
Name.SkipPubSection)
1246 if (!HeaderEmitted) {
1248 Asm->emitLabelDifference(EndLabel, BeginLabel, 4);
1249 Asm->OutStreamer->emitLabel(BeginLabel);
1251 Asm->emitInt32(
Unit.getStartOffset());
1252 Asm->emitInt32(
Unit.getNextUnitOffset() -
Unit.getStartOffset());
1253 HeaderEmitted =
true;
1255 Asm->emitInt32(
Name.Die->getOffset());
1258 Asm->OutStreamer->emitBytes(
Name.Name.getString());
1266 Asm->OutStreamer->emitLabel(EndLabel);
1271 emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
1272 "names", Unit, Unit.getPubnames());
1277 emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
1278 "types", Unit, Unit.getPubtypes());
1283 MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
1285 MS->emitBytes(CIEBytes);
1286 FrameSectionSize += CIEBytes.
size();
1294 MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
1296 MS->emitIntValue(FDEBytes.
size() + 4 + AddrSize, 4);
1297 MS->emitIntValue(CIEOffset, 4);
1298 MS->emitIntValue(
Address, AddrSize);
1299 MS->emitBytes(FDEBytes);
1300 FrameSectionSize += FDEBytes.
size() + 8 + AddrSize;
1306 assert(Context !=
nullptr &&
"Empty DWARF context");
1310 MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection());
1311 emitMacroTableImpl(Table, UnitMacroMap,
StringPool, MacInfoSectionSize);
1316 MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection());
1317 emitMacroTableImpl(Table, UnitMacroMap,
StringPool, MacroSectionSize);
1321void DwarfStreamer::emitMacroTableImpl(
const DWARFDebugMacro *MacroTable,
1325 bool DefAttributeIsReported =
false;
1326 bool UndefAttributeIsReported =
false;
1327 bool ImportAttributeIsReported =
false;
1328 for (
const DWARFDebugMacro::MacroList &
List : MacroTable->MacroLists) {
1330 if (UnitIt == UnitMacroMap.
end()) {
1332 "couldn`t find compile unit for the macro table with offset = {0:x}",
1338 DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE();
1339 if (OutputUnitDIE ==
nullptr)
1344 bool hasDWARFv5Header =
false;
1345 for (
auto &V : OutputUnitDIE->
values()) {
1346 if (V.getAttribute() == dwarf::DW_AT_macro_info) {
1349 }
else if (V.getAttribute() == dwarf::DW_AT_macros) {
1350 hasDWARFv5Header =
true;
1357 if (hasDWARFv5Header) {
1359 MS->emitIntValue(
List.Header.Version,
sizeof(
List.Header.Version));
1360 OutOffset +=
sizeof(
List.Header.Version);
1366 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
1367 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
1368 warn(
"opcode_operands_table is not supported yet.");
1372 std::optional<uint64_t> StmtListOffset;
1373 if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
1375 for (
auto &V : OutputUnitDIE->
values()) {
1376 if (
V.getAttribute() == dwarf::DW_AT_stmt_list) {
1377 StmtListOffset =
V.getDIEInteger().getValue();
1382 if (!StmtListOffset) {
1383 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
1384 warn(
"couldn`t find line table for macro table.");
1389 MS->emitIntValue(Flags,
sizeof(Flags));
1390 OutOffset +=
sizeof(
Flags);
1393 if (StmtListOffset) {
1394 MS->emitIntValue(*StmtListOffset,
List.Header.getOffsetByteSize());
1395 OutOffset +=
List.Header.getOffsetByteSize();
1400 for (
const DWARFDebugMacro::Entry &MacroEntry :
List.Macros) {
1401 if (MacroEntry.Type == 0) {
1402 OutOffset += MS->emitULEB128IntValue(MacroEntry.Type);
1406 uint8_t MacroType = MacroEntry.Type;
1407 switch (MacroType) {
1409 bool HasVendorSpecificExtension =
1414 if (HasVendorSpecificExtension) {
1416 MS->emitIntValue(MacroType, 1);
1420 OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant);
1423 StringRef
String = MacroEntry.ExtStr;
1425 MS->emitIntValue(0, 1);
1426 OutOffset +=
String.size() + 1;
1428 warn(
"unknown macro type. skip.");
1436 case dwarf::DW_MACRO_define:
1437 case dwarf::DW_MACRO_undef: {
1439 MS->emitIntValue(MacroType, 1);
1443 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
1446 StringRef
String = MacroEntry.MacroStr;
1448 MS->emitIntValue(0, 1);
1449 OutOffset +=
String.size() + 1;
1451 case dwarf::DW_MACRO_define_strp:
1452 case dwarf::DW_MACRO_undef_strp:
1453 case dwarf::DW_MACRO_define_strx:
1454 case dwarf::DW_MACRO_undef_strx: {
1455 assert(UnitIt->second->getOrigUnit().getVersion() >= 5);
1459 switch (MacroType) {
1460 case dwarf::DW_MACRO_define_strx: {
1461 MacroType = dwarf::DW_MACRO_define_strp;
1462 if (!DefAttributeIsReported) {
1463 warn(
"DW_MACRO_define_strx unsupported yet. Convert to "
1464 "DW_MACRO_define_strp.");
1465 DefAttributeIsReported =
true;
1468 case dwarf::DW_MACRO_undef_strx: {
1469 MacroType = dwarf::DW_MACRO_undef_strp;
1470 if (!UndefAttributeIsReported) {
1471 warn(
"DW_MACRO_undef_strx unsupported yet. Convert to "
1472 "DW_MACRO_undef_strp.");
1473 UndefAttributeIsReported =
true;
1482 MS->emitIntValue(MacroType, 1);
1486 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
1489 DwarfStringPoolEntryRef EntryRef =
1490 StringPool.
getEntry(MacroEntry.MacroStr);
1491 MS->emitIntValue(EntryRef.
getOffset(),
List.Header.getOffsetByteSize());
1492 OutOffset +=
List.Header.getOffsetByteSize();
1495 case dwarf::DW_MACRO_start_file: {
1497 MS->emitIntValue(MacroType, 1);
1500 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
1502 OutOffset += MS->emitULEB128IntValue(MacroEntry.File);
1504 case dwarf::DW_MACRO_end_file: {
1506 MS->emitIntValue(MacroType, 1);
1509 case dwarf::DW_MACRO_import:
1510 case dwarf::DW_MACRO_import_sup: {
1511 if (!ImportAttributeIsReported) {
1512 warn(
"DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. "
1514 ImportAttributeIsReported =
true;
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This class holds an abstract representation of an Accelerator Table, consisting of a sequence of buck...
A class that represents an address range.
The AddressRanges class helps normalize address range collections.
static dwarf::Form BestForm(bool IsSigned, uint64_t Int)
Choose the best form for integer.
A structured debug information entry.
The Data class implementation for DWARF v5 accelerator table.
DWARFContext This data structure is the top level entity that deals with dwarf debug information pars...
iterator find(const_arg_type_t< KeyT > Val)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
uint64_t getOffset() const
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Context object for machine code objects.
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 a uniqued identifier for a section in the current translation unit.
void setAlignment(Align Value)
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.
void emitInt16(uint64_t Value)
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 switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
void emitInt8(uint64_t Value)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
A string table that doesn't need relocations.
LLVM_ABI DwarfStringPoolEntryRef getEntry(StringRef S)
LLVM_ABI std::vector< DwarfStringPoolEntryRef > getEntriesForEmission() const
Return the list of strings to be emitted.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
Target - Wrapper for Target specific information.
TargetMachine * createTargetMachine(const Triple &TT, StringRef CPU, StringRef Features, const TargetOptions &Options, std::optional< Reloc::Model > RM, std::optional< CodeModel::Model > CM=std::nullopt, CodeGenOptLevel OL=CodeGenOptLevel::Default, bool JIT=false) const
createTargetMachine - Create a target specific machine implementation for the specified Triple.
MCRegisterInfo * createMCRegInfo(const Triple &TT) const
Create a MCRegisterInfo implementation.
MCCodeEmitter * createMCCodeEmitter(const MCInstrInfo &II, MCContext &Ctx) const
createMCCodeEmitter - Create a target specific code emitter.
MCObjectFileInfo * createMCObjectFileInfo(MCContext &Ctx, bool PIC, bool LargeCodeModel=false) const
Create a MCObjectFileInfo implementation for the specified target triple.
MCAsmInfo * createMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TheTriple, const MCTargetOptions &Options) const
Create a MCAsmInfo implementation for the specified target triple.
MCAsmBackend * createMCAsmBackend(const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options) const
createMCAsmBackend - Create a target specific assembly parser.
LLVM_ABI MCStreamer * createAsmStreamer(MCContext &Ctx, std::unique_ptr< formatted_raw_ostream > OS, std::unique_ptr< MCInstPrinter > IP, std::unique_ptr< MCCodeEmitter > CE, std::unique_ptr< MCAsmBackend > TAB) const
LLVM_ABI MCStreamer * createMCObjectStreamer(const Triple &T, MCContext &Ctx, std::unique_ptr< MCAsmBackend > TAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter, const MCSubtargetInfo &STI) const
Create a target specific MCStreamer.
MCInstPrinter * createMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI) const
MCSubtargetInfo * createMCSubtargetInfo(const Triple &TheTriple, StringRef CPU, StringRef Features) const
createMCSubtargetInfo - Create a MCSubtargetInfo implementation.
AsmPrinter * createAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > &&Streamer) const
createAsmPrinter - Create a target specific assembly printer pass.
MCInstrInfo * createMCInstrInfo() const
createMCInstrInfo - Create a MCInstrInfo implementation.
Triple - Helper class for working with autoconf configuration names.
const std::string & getTriple() const
std::function< void( const Twine &Warning, StringRef Context, const DWARFDie *DIE)> MessageHandlerTy
OutputFileType
Type of output file.
uint64_t getValueIndex(T Value)
Stores all information relating to a compile unit, be it in its original instance in the object file ...
Error emitDwarfDebugLocListFragment(const CompileUnit &Unit, const DWARFLocationExpressionsVector &LinkedLocationExpression, PatchLocation Patch, DebugDieValuePool &AddrPool) override
Emit debug ranges(.debug_loc, .debug_loclists) fragment.
void emitDwarfDebugAddrsFooter(const CompileUnit &Unit, MCSymbol *EndLabel) override
Emit .debug_addr footer.
void emitDwarfDebugArangesTable(const CompileUnit &Unit, const AddressRanges &LinkedRanges) override
Emit .debug_aranges entries for Unit.
void emitLineTableForUnit(const DWARFDebugLine::LineTable &LineTable, const CompileUnit &Unit, OffsetsStringPool &DebugStrPool, OffsetsStringPool &DebugLineStrPool, std::vector< uint64_t > *RowOffsets=nullptr) override
Emit .debug_line table entry for specified LineTable The optional parameter RowOffsets,...
void emitAppleTypes(AccelTable< AppleAccelTableStaticTypeData > &Table) override
Emit Apple type accelerator table.
void emitDIE(DIE &Die) override
Recursively emit the DIE tree rooted at Die.
void emitStrings(const NonRelocatableStringpool &Pool) override
Emit the string table described by Pool into .debug_str table.
static Expected< std::unique_ptr< DwarfStreamer > > createStreamer(const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType, raw_pwrite_stream &OutFile, DWARFLinkerBase::MessageHandlerTy Warning)
void emitDebugNames(DWARF5AccelTable &Table) override
Emit DWARF debug names.
void emitDwarfDebugLocListFooter(const CompileUnit &Unit, MCSymbol *EndLabel) override
Emit debug ranges(.debug_loc, .debug_loclists) footer.
MCSymbol * emitDwarfDebugAddrsHeader(const CompileUnit &Unit) override
Emit .debug_addr header.
void emitStringOffsets(const SmallVector< uint64_t > &StringOffset, uint16_t TargetDWARFVersion) override
Emit the debug string offset table described by StringOffsets into the .debug_str_offsets table.
void emitLineStrings(const NonRelocatableStringpool &Pool) override
Emit the string table described by Pool into .debug_line_str table.
Error init(Triple TheTriple, StringRef Swift5ReflectionSegmentName)
void emitSwiftReflectionSection(llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, StringRef Buffer, uint32_t Alignment, uint32_t Size)
Emit the swift reflection section stored in Buffer.
MCSymbol * emitDwarfDebugRangeListHeader(const CompileUnit &Unit) override
Emit debug ranges(.debug_ranges, .debug_rnglists) header.
void emitCIE(StringRef CIEBytes) override
Emit a CIE.
void emitSectionContents(StringRef SecData, DebugSectionKind SecKind) override
Emit contents of section SecName From Obj.
void emitAppleNames(AccelTable< AppleAccelTableStaticOffsetData > &Table) override
Emit Apple names accelerator table.
void finish() override
Dump the file to the disk.
void emitAbbrevs(const std::vector< std::unique_ptr< DIEAbbrev > > &Abbrevs, unsigned DwarfVersion) override
Emit the abbreviation table Abbrevs to the debug_abbrev section.
MCSymbol * emitDwarfDebugLocListHeader(const CompileUnit &Unit) override
Emit debug locations(.debug_loc, .debug_loclists) header.
void emitFDE(uint32_t CIEOffset, uint32_t AddreSize, uint64_t Address, StringRef Bytes) override
Emit an FDE with data Bytes.
void emitPubNamesForUnit(const CompileUnit &Unit) override
Emit the .debug_pubnames contribution for Unit.
void emitPubTypesForUnit(const CompileUnit &Unit) override
Emit the .debug_pubtypes contribution for Unit.
void emitDwarfDebugAddrs(const SmallVector< uint64_t > &Addrs, uint8_t AddrSize) override
Emit the addresses described by Addrs into .debug_addr table.
void emitAppleObjc(AccelTable< AppleAccelTableStaticOffsetData > &Table) override
Emit Apple Objective-C accelerator table.
void emitAppleNamespaces(AccelTable< AppleAccelTableStaticOffsetData > &Table) override
Emit Apple namespaces accelerator table.
void emitMacroTables(DWARFContext *Context, const Offset2UnitMap &UnitMacroMap, OffsetsStringPool &StringPool) override
Emit all available macro tables(DWARFv4 and DWARFv5).
void switchToDebugInfoSection(unsigned DwarfVersion)
Set the current output section to debug_info and change the MC Dwarf version to DwarfVersion.
void emitCompileUnitHeader(CompileUnit &Unit, unsigned DwarfVersion) override
Emit the compilation unit header for Unit in the debug_info section.
void emitSwiftAST(StringRef Buffer)
Emit the swift_ast section stored in Buffer.
Error emitDwarfDebugRangeListFragment(const CompileUnit &Unit, const AddressRanges &LinkedRanges, PatchLocation Patch, DebugDieValuePool &AddrPool) override
Emit debug ranges(.debug_ranges, .debug_rnglists) fragment.
void emitDwarfDebugRangeListFooter(const CompileUnit &Unit, MCSymbol *EndLabel) override
Emit debug ranges(.debug_ranges, .debug_rnglists) footer.
An abstract base class for streams implementations that also support a pwrite operation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
IndexedValuesMap< uint64_t > DebugDieValuePool
DenseMap< uint64_t, CompileUnit * > Offset2UnitMap
DebugSectionKind
List of tracked debug tables.
std::optional< const char * > toString(const std::optional< DWARFFormValue > &V)
Take an optional DWARFFormValue and try to extract a string value from it.
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_ARANGES_VERSION
Section version number for .debug_aranges.
@ DW_PUBNAMES_VERSION
Section version number for .debug_pubnames.
@ DW_LENGTH_DWARF64
Indicator of 64-bit DWARF format.
LLVM_ABI MCTargetOptions InitMCTargetOptionsFromFlags()
This is an optimization pass for GlobalISel generic memory operations.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
uint64_t offsetToAlignment(uint64_t Value, Align Alignment)
Returns the offset to the next integer (mod 2**64) that is greater than or equal to Value and is a mu...
LLVM_ABI unsigned getULEB128Size(uint64_t Value)
Utility function to get the size of the ULEB128-encoded value.
void emitAppleAccelTable(AsmPrinter *Asm, AccelTable< DataT > &Contents, StringRef Prefix, const MCSymbol *SecBegin)
Emit an Apple Accelerator Table consisting of entries in the specified AccelTable.
LLVM_ABI void emitDWARF5AccelTable(AsmPrinter *Asm, DWARF5AccelTable &Contents, const DwarfDebug &DD, ArrayRef< std::unique_ptr< DwarfCompileUnit > > CUs)
StrongType< NonRelocatableStringpool, OffsetsTag > OffsetsStringPool
LLVM_ABI unsigned getSLEB128Size(int64_t Value)
Utility function to get the size of the SLEB128-encoded value.
std::vector< DWARFLocationExpression > DWARFLocationExpressionsVector
Represents a set of absolute location expressions.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint8_t MinInstLength
The size in bytes of the smallest target machine instruction.
int8_t LineBase
This parameter affects the meaning of the special opcodes. See below.
uint8_t LineRange
This parameter affects the meaning of the special opcodes. See below.
uint8_t OpcodeBase
The number assigned to the first special opcode.
dwarf::FormParams FormParams
Version, address size (starting in v5), and DWARF32/64 format; these parameters affect interpretation...
Represents a single DWARF expression, whose value is location-dependent.
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.
static const Target * lookupTarget(StringRef TripleStr, std::string &Error)
lookupTarget - Lookup a target based on a target triple.
void set(uint64_t New) const