xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "DwarfFile.h"
100b57cec5SDimitry Andric #include "DwarfCompileUnit.h"
110b57cec5SDimitry Andric #include "DwarfDebug.h"
120b57cec5SDimitry Andric #include "DwarfUnit.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
140b57cec5SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
160b57cec5SDimitry Andric #include <cstdint>
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric using namespace llvm;
190b57cec5SDimitry Andric 
DwarfFile(AsmPrinter * AP,StringRef Pref,BumpPtrAllocator & DA)200b57cec5SDimitry Andric DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA)
210b57cec5SDimitry Andric     : Asm(AP), Abbrevs(AbbrevAllocator), StrPool(DA, *Asm, Pref) {}
220b57cec5SDimitry Andric 
addUnit(std::unique_ptr<DwarfCompileUnit> U)230b57cec5SDimitry Andric void DwarfFile::addUnit(std::unique_ptr<DwarfCompileUnit> U) {
240b57cec5SDimitry Andric   CUs.push_back(std::move(U));
250b57cec5SDimitry Andric }
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric // Emit the various dwarf units to the unit section USection with
280b57cec5SDimitry Andric // the abbreviations going into ASection.
emitUnits(bool UseOffsets)290b57cec5SDimitry Andric void DwarfFile::emitUnits(bool UseOffsets) {
300b57cec5SDimitry Andric   for (const auto &TheU : CUs)
310b57cec5SDimitry Andric     emitUnit(TheU.get(), UseOffsets);
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric 
emitUnit(DwarfUnit * TheU,bool UseOffsets)340b57cec5SDimitry Andric void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
350b57cec5SDimitry Andric   if (TheU->getCUNode()->isDebugDirectivesOnly())
360b57cec5SDimitry Andric     return;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   MCSection *S = TheU->getSection();
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric   if (!S)
410b57cec5SDimitry Andric     return;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   // Skip CUs that ended up not being needed (split CUs that were abandoned
440b57cec5SDimitry Andric   // because they added no information beyond the non-split CU)
45bdd1243dSDimitry Andric   if (TheU->getUnitDie().values().empty())
460b57cec5SDimitry Andric     return;
470b57cec5SDimitry Andric 
4881ad6265SDimitry Andric   Asm->OutStreamer->switchSection(S);
490b57cec5SDimitry Andric   TheU->emitHeader(UseOffsets);
500b57cec5SDimitry Andric   Asm->emitDwarfDIE(TheU->getUnitDie());
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   if (MCSymbol *EndLabel = TheU->getEndLabel())
535ffd83dbSDimitry Andric     Asm->OutStreamer->emitLabel(EndLabel);
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric // Compute the size and offset for each DIE.
computeSizeAndOffsets()570b57cec5SDimitry Andric void DwarfFile::computeSizeAndOffsets() {
580b57cec5SDimitry Andric   // Offset from the first CU in the debug info section is 0 initially.
59e8d8bef9SDimitry Andric   uint64_t SecOffset = 0;
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   // Iterate over each compile unit and set the size and offsets for each
620b57cec5SDimitry Andric   // DIE within each compile unit. All offsets are CU relative.
630b57cec5SDimitry Andric   for (const auto &TheU : CUs) {
640b57cec5SDimitry Andric     if (TheU->getCUNode()->isDebugDirectivesOnly())
650b57cec5SDimitry Andric       continue;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric     // Skip CUs that ended up not being needed (split CUs that were abandoned
680b57cec5SDimitry Andric     // because they added no information beyond the non-split CU)
69bdd1243dSDimitry Andric     if (TheU->getUnitDie().values().empty())
700b57cec5SDimitry Andric       return;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric     TheU->setDebugSectionOffset(SecOffset);
730b57cec5SDimitry Andric     SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
740b57cec5SDimitry Andric   }
75e8d8bef9SDimitry Andric   if (SecOffset > UINT32_MAX && !Asm->isDwarf64())
76e8d8bef9SDimitry Andric     report_fatal_error("The generated debug information is too large "
77e8d8bef9SDimitry Andric                        "for the 32-bit DWARF format.");
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
computeSizeAndOffsetsForUnit(DwarfUnit * TheU)800b57cec5SDimitry Andric unsigned DwarfFile::computeSizeAndOffsetsForUnit(DwarfUnit *TheU) {
810b57cec5SDimitry Andric   // CU-relative offset is reset to 0 here.
82e8d8bef9SDimitry Andric   unsigned Offset = Asm->getUnitLengthFieldByteSize() + // Length of Unit Info
830b57cec5SDimitry Andric                     TheU->getHeaderSize();              // Unit-specific headers
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   // The return value here is CU-relative, after laying out
860b57cec5SDimitry Andric   // all of the CU DIE.
870b57cec5SDimitry Andric   return computeSizeAndOffset(TheU->getUnitDie(), Offset);
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric // Compute the size and offset of a DIE. The offset is relative to start of the
910b57cec5SDimitry Andric // CU. It returns the offset after laying out the DIE.
computeSizeAndOffset(DIE & Die,unsigned Offset)920b57cec5SDimitry Andric unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
9304eeddc0SDimitry Andric   return Die.computeOffsetsAndAbbrevs(Asm->getDwarfFormParams(), Abbrevs,
9404eeddc0SDimitry Andric                                       Offset);
950b57cec5SDimitry Andric }
960b57cec5SDimitry Andric 
emitAbbrevs(MCSection * Section)970b57cec5SDimitry Andric void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric // Emit strings into a string section.
emitStrings(MCSection * StrSection,MCSection * OffsetSection,bool UseRelativeOffsets)1000b57cec5SDimitry Andric void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
1010b57cec5SDimitry Andric                             bool UseRelativeOffsets) {
1020b57cec5SDimitry Andric   StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
addScopeVariable(LexicalScope * LS,DbgVariable * Var)105*5f757f3fSDimitry Andric void DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
1060b57cec5SDimitry Andric   auto &ScopeVars = ScopeVariables[LS];
1070b57cec5SDimitry Andric   const DILocalVariable *DV = Var->getVariable();
1080b57cec5SDimitry Andric   if (unsigned ArgNum = DV->getArg()) {
109*5f757f3fSDimitry Andric     auto Ret = ScopeVars.Args.insert({ArgNum, Var});
110*5f757f3fSDimitry Andric     assert(Ret.second);
111*5f757f3fSDimitry Andric     (void)Ret;
1120b57cec5SDimitry Andric   } else {
1130b57cec5SDimitry Andric     ScopeVars.Locals.push_back(Var);
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
addScopeLabel(LexicalScope * LS,DbgLabel * Label)1170b57cec5SDimitry Andric void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
1180b57cec5SDimitry Andric   SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
1190b57cec5SDimitry Andric   Labels.push_back(Label);
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric std::pair<uint32_t, RangeSpanList *>
addRange(const DwarfCompileUnit & CU,SmallVector<RangeSpan,2> R)1230b57cec5SDimitry Andric DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
1240b57cec5SDimitry Andric   CURangeLists.push_back(
125480093f4SDimitry Andric       RangeSpanList{Asm->createTempSymbol("debug_ranges"), &CU, std::move(R)});
1260b57cec5SDimitry Andric   return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
1270b57cec5SDimitry Andric }
128